Transferindo grande quantidade (84 milhões de linhas) de dados com eficiência

11

Eu tenho cerca de 84 milhões de linhas. Desses, todos eles precisam ser transferidos para um banco de dados separado no mesmo servidor, e excluo para excluir cerca de 60 milhões de linhas do banco de dados de origem.

Os 84 milhões de linhas estão todos na mesma tabela. Somente essa tabela responde por 90% de todo o banco de dados.

Então ... Fonte: 84 milhões de linhas -> 24 milhões de linhas Destino: 0 linhas -> 84 milhões de linhas

A fonte está executando o modo de recuperação completa, o destino estará executando de forma simples.

Gostaria de saber qual seria a maneira mais eficiente de fazer isso?

Plano A:

1) INSERIR NO destino SELECIONE * DA fonte

2) TRUNCATE fonte

3) INSERT NA fonte SELECT * FROM destino ONDE keep_condition = 1

Plano B:

1) Restaure um backup do banco de dados de origem como o banco de dados de destino

2) Solte todas as tabelas, exceto a necessária no banco de dados de destino

3) Fonte TRUNCATE

4) INSERIR NA ORIGEM SELECIONE * DO destino ONDE keep_condition = 1

Plano C:

1) INSERIR NO destino SELECIONE * DA fonte

2) DELETE source WHERE keep_condition = 0

ou alguma outra coisa?

obrigado

elty123
fonte
por que você não usa o assistente para importar e exportar dados? é uma ferramenta fornecida com a instalação do SQL Server.
Hani El Mouallem 26/09/14
É possível copiar as 24 mil linhas para uma nova tabela e simplesmente renomeá-las conforme necessário para que você nunca mova 84 milhões de linhas desnecessariamente?
LowlyDBA
Esse é um processo único ou contínuo? Eu pergunto porque, dado o tempo necessário para processar 80 milhões de linhas, é provável que haja alterações de dados em SOURCE produzindo linhas que agora devem estar em DESTINATION.
Michael Green
Isso parece um problema XY: você precisa terminar com todas as linhas de 84MM em um banco de dados e 24MM daquelas em um segundo banco de dados. Que requisito comercial requer que 84MM sejam movidos e 60M excluídos, em vez de apenas mover 24MM? link: meta.stackexchange.com/questions/66377/what-is-the-xy-problem )
Pieter Geerkens
Eu tenho um problema muito semelhante e claramente não é XY. Antes da proliferação de leis relativas à retenção de registros, mantivemos todos os dados. Agora devemos excluir linhas anteriores à data em que somos legalmente obrigados a mantê-las. Isso significa arquivar e excluir mais de 20 anos de dados, porque a retenção legal na maioria dos casos é de 7 anos. Eu não acho que estou sozinho acreditando que a Microsoft é negligente por não fornecer a funcionalidade de 'cópia em massa' aos procedimentos armazenados. Um aplicativo não deve ser mais rápido na movimentação de dados 'dentro' de um banco de dados do que o próprio banco de dados. No próximo ano, outro ano deve ser arquivado.
Bielawski 6/05/19

Respostas:

11

Eu acrescentaria que, por mais que você decida abordar isso, precisará lote essas transações . Ultimamente, tive muita sorte com o artigo vinculado e aprecio a maneira como ele tira proveito dos índices, em oposição à maioria das soluções em lote que vejo.

Mesmo minimamente registrados, essas são grandes transações , e você pode gastar muito tempo lidando com as ramificações do crescimento anormal de logs (VLFs, truncamento, dimensionamento correto etc.).

obrigado

Erik Darling
fonte
3

"Eficiente" pode ser aplicado ao uso do arquivo de log, desempenho de E / S, tempo da CPU ou tempo de execução.

Eu tentaria obter uma operação minimamente registrada, o que seria bastante eficiente do ponto de vista do log. Isso deve economizar um tempo de execução. Se você tiver o espaço tempdb, o seguinte pode funcionar para você.

CREATE TABLE #temp;
ALTER source -> BULK_LOGGED recovery model

BEGIN TRANSACTION;

    INSERT INTO dest SELECT FROM source;
    INSERT INTO #temp SELECT FROM source WHERE keep_condition=1;
    TRUNCATE TABLE source;
    INSERT INTO source SELECT FROM #temp;

COMMIT TRANSACTION;

ALTER source -> FULL recovery model
DROP TABLE #temp;

Para que uma operação minimamente registrada ocorra, várias condições precisam ser verdadeiras, incluindo nenhum backup em execução no momento, banco de dados definido para o BULK_LOGGEDmodo de recuperação e, dependendo dos seus índices, a tabela de destino pode estar vazia. Alguns desses comportamentos também foram alterados (aprimorados) do SQL Server 2005 para 2008.

Por outro lado, sem conhecer as especificidades da sua tabela e dados, qualquer uma das suas outras opções pode ter um desempenho melhor. Tente usar

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

.. e veja qual funciona melhor.

EDIT : Ao executar operações de log em massa, faça um backup (log completo ou de transações) antes e depois da operação, se você precisar de um recurso de restauração pontual e suspeitar que outras atividades possam estar acontecendo no banco de dados em ao mesmo tempo em que seu trabalho ETL está em execução.

Escrevi um post sobre operações minimamente registradas há um tempo atrás, há links para outros posts e documentação.

Daniel Hutmacher
fonte
+1 por aconselhar o OP a testar para ver qual funciona melhor. Claro, isso pode ser um pouco difícil obter números reais a menos que (s) que ele tem um sistema duplicado em dev, etc.
Max Vernon
Apenas uma pergunta: o que aconteceria se você tentasse restaurar um ponto no tempo quando o banco de dados estivesse no modo de log em massa? Supus que qualquer transação que não seja qualificada como "em massa" seria recuperável.
elty123
11
@ elty123 Na recuperação de log em massa, você só pode restaurar o final do seu último backup de log. Não há nenhum ponto no tempo de recuperação, como seria com a recuperação total. Normalmente, você alterna para a recuperação registrada em massa, executa algum processo de ETL, volta ao máximo e depois faz um backup do log.
RubberChickenLeader
@WindRaven Isso não está correto - veja minha resposta abaixo.
wBob 27/09/14
11
@wBob e @WindRaven, atualizei minha resposta para refletir a necessidade de fazer backups antes e depois de usar o BULK_LOGGEDmodo. Obrigado!
Daniel Hutmacher
1

Por que não o BCP?

  1. Fazer backup do sourcedb
  2. Alterar sourcedb para logon em massa
  3. Abrir prompt de comando

  4. bcp server.sourcedb.table out Filename.flt -T -c

  5. bcp "SELECT * FROM sourcedb.table WHERE keep_condition = 1" queryout Filename2.flt -T -c

  6. bcp Server.destinationdb.table in Filename.flt -T -c -b1000

  7. verifique os dados

  8. No SSMS, truncar a tabela de origem
  9. bcp server.sourcedb.table in Filename2.flt -T -c -b1000
  10. Alterar o sourcedb de volta para completo
stacylaray
fonte
2
Porque eles estão no mesmo servidor. Escrever no sistema de arquivos seria caro. Melhor criar um banco de dados e configurá-lo, aproveitando a inicialização instantânea de arquivos. Essa seria uma escolha razoável para dbs em servidores diferentes, embora o SSIS fosse minha primeira opção, se disponível. Nota: a opção -n (nativa) é mais compacta e segura para mover dados do SQL Server para o SQL Server. A opção -b não tem efeito para saída de bcp.
wBob 27/09/14
0

Não pense que você deveria recomendar a alteração do modelo de recuperação sem um backup completo do banco de dados ou um backup t-log antes e depois . Um dos recursos do modelo de recuperação BULK_LOGGED é que você perderá a capacidade de fazer a recuperação pontual para logs t que contêm operações com registro em massa. Cenário clássico: backup completo noturno, backups diários de t-log. Você altera o modelo de recuperação para logon em massa e inicia sua operação. Algo dá errado e a transação é revertida (ou você não usou uma). No entanto, você não tem certeza do que mais estava acontecendo no banco de dados, portanto, você deseja restaurar para um bom ponto conhecido.

Quando você pode restaurar de volta para? Último backup t-log de hora em hora que não contém operações de log em massa, potencialmente perdendo n minutos de transações. Um backup completo ou backup t-log antes de alterar o modelo de recuperação criará um ponto de fallback. Qual você escolhe depende do seu RTO.

wBob
fonte
0

Descartar partições de uma tabela é uma maneira muito rápida e eficiente em termos de recursos de remover grandes pedaços de dados de uma tabela. Se essa tabela fosse particionada de uma maneira que suporte sua divisão de origem / destino, a resposta seria restaurar uma cópia, descartar as tabelas redundantes e as partições redundantes do destino e soltar as partições complementares da origem.

No entanto, o custo de ativar o particionamento pode tornar essa operação mais cara em geral.

Michael Green
fonte