Pergunta

Eu quero swap para tabelas na melhor maneira possível.
Eu tenho uma tabela IPToCountry, e eu criar um novo em uma base semanal de acordo com um arquivo CSV externo que eu importar.

A maneira mais rápida que eu encontrei para fazer a troca estava fazendo o seguinte:

sp_rename IpToCountry IpToCountryOld
go
sp_rename IpToCountryNew IpToCountry
go

O problema com isto é que a tabela ainda pode ser acessado no meio.
Como faço para abordar este problema no SQL?
Em considerou usando sp_getapplock e sp_releaseapplock, mas eu quero manter a leitura a partir da função de tabela o mais rápido possível.

Foi útil?

Solução

Supondo que você é incapaz de atualização / inserir na tabela existente, por que não envolva todo o acesso à tabela usando um vista ?

Por exemplo, você pode inicialmente armazenar seus dados em uma tabela chamada IpToCountry20090303 , e seu ponto de vista seria algo como isto:

CREATE VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090303

Quando os novos dados vem em, você pode criar e preencher o IpToCountry20090310 mesa. Uma vez que a tabela é preenchida apenas atualizar o seu ponto de vista:

ALTER VIEW IpToCountry
AS
SELECT * FROM IpToCountry20090310

O interruptor será completamente atômica, sem necessidade de qualquer bloqueios explícitos ou transações. Uma vez que o ponto de vista foi atualizado, você pode simplesmente deixar cair a tabela antiga (ou mantê-lo se você preferir).

Outras dicas

Outro método para implementar o que você está olhando para conseguir seria o uso de particionamento de tabela, uma técnica que está disponível na edição Enterprise do SQL Server.

O nome da tabela pode permanecer o mesmo. Após a sua importação tabela é completa, você simplesmente mudar a partição que contém os dados antigos e interruptor na nova partição.

A seguir Livro Branco contém todas as informações que você precisa para começar.

http://msdn.microsoft.com/en-us/library /ms345146.aspx

Cheers, John

Eu tive problemas para obter funções de particionamento para trabalhar em escala. Criar e eliminar partição são operações de bloqueio, e você tem pouco controle sobre o bloqueio, e se não puder obter um bloqueio irá falhar com um nível de gravidade 16 e matar sua conexão - o que você não pode prender e repetição sem restabelecimento a conexão. Mas pode funcionar muito bem para você. Além disso, MSS Enterprise Edition é necessária, você não pode usar SE - pode ser demais para algumas lojas menores ou mais em causa custo.

Eu também encontrei o ponto de vista REDEF ao bloco em alta escala (= transação de volume + pura volume de dados constantemente-inseridos, no meu caso) em sys tabelas e objetos, assim que essas operações podem impasse em coisas como reindexação e DTCCs - e em um caso, especificamente com um usuário no SSMS (de todas as coisas) tentando navegar vistas no Object Explorer (precisa de alguém para dizer que esses caras sobre READPAST). Mais uma vez, sua milhagem pode variar.

Em contraste, o sp_rename funciona bem para mim em escala: dá-lhe o controle sobre o bloqueio e o alcance do mesmo. Para resolver o problema de bloqueio antes da troca, experimentá-lo como mostrado abaixo. Pelo seu valor nominal este parece ter o mesmo problema escala em alto volume ... mas eu não vi isso na prática. Assim, funciona para mim ... mas, novamente, necessidades e experiências de todos são diferentes.

DECLARE @dummylock bit 
BEGIN TRANSACTION 
BEGIN TRY
   -- necessary to obtain exclusive lock on the table prior to swapping
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM A WITH (TABLOCKX))
   -- may or may not be necessary in your case
   SELECT @dummylock = 1 WHERE EXISTS (SELECT 1 FROM B WITH (TABLOCKX))
   exec sp_rename 'A', 'TEMP'
   exec sp_rename 'B', 'A'
   exec sp_rename 'TEMP', 'B'
   COMMIT TRANSACTION
END TRY
BEGIN CATCH
   -- other error handling here if needed
   ROLLBACK TRANSACTION 
END CATCH

O que acontece com IpToCountryOld? Você jogá-lo fora? Nesse caso, por que não truncar IPToCountry e importar minha nova dados.

Se você precisa manter os dados, como sobre o armazenamento a data de carga na tabela e armazenar o "atual" data de carga em algum lugar para ser usado em uma cláusula WHERE? Então você mudar a data atual, quando os dados são carregados com sucesso.

Você não diz qual DB que você está usando, então eu não sei o quanto o uso é isso, mas você tem quaisquer procedimentos armazenados que fazem referência a mesa? Esteja avisado que em algumas plataformas SPs são compilados utilizando referências internas para tabelas que não vai mudar com uma mudança de nome, então há um risco de que SPs não vai pegar seus novos dados, sem uma recompilação. O mesmo pode ser verdade para vistas e armazenados consultas analisados.

Você pode não fazer a importação para uma tabela de durante horas de folga?

Ou porque não basta fazer uma atualização de dados, ou seja, actualizar os registos existentes e adicionar quaisquer novos em um registro por base registro como você loop para importar os dados. Isso permitiria que a mesa para ficar vivo e reduzir o impacto global da adição e eliminação de tabelas completas.

Qual é a estrutura dos dados que está sendo importado, design mesa, formato, PK, etc? Desde que sejamos capazes de lhe dar uma resposta melhor.

Apenas correu para um problema semelhante trabalhando em uma tabela de preparação que teve problemas de escala com fechaduras adequadas.

Em todos os lugares a sua tabela é referenciada você poderia chamar um procedimento armazenado pedindo o nome da tabela.

O procedimento armazenado seria opcionalmente criar a nova tabela (s) ou retornar as tabelas antigas, dependendo dos parâmetros fornecidos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top