Qual é o melhor método para atualizar apenas algumas tabelas em um banco de dados de teste da produção?

12

Eu tenho um banco de dados de produção muito grande e um banco de dados de ambiente de teste muito grande no SQL Server 2008R2. Ambos os bancos de dados têm estrutura de tabela semelhante, mas diferentes usuários / logins / permissões / funções.

Eu preciso atualizar apenas algumas tabelas no banco de dados de teste periodicamente da produção, cerca de uma vez por mês.

A maneira atual em que planejo fazer isso é

  1. Use o utilitário BCP para fazer uma exportação das tabelas necessárias de Produção.
  2. Copie o arquivo de exportação bcp no servidor de teste
  3. Desativar índices e restrições em todas as tabelas que estou atualizando no teste
  4. Truncar as tabelas de banco de dados de teste
  5. Carregue os dados novamente nas tabelas de banco de dados de teste usando o BCP.
  6. reconstruir índices e reativar restrições em Teste

Tudo isso parece um pouco complicado demais para uma tarefa tão pequena. Também parece que isso geraria muito refazer (no t-log). Existe uma maneira melhor de fazer isso?

Outra maneira que pensei em fazer isso é restaurar um backup do Production para o ambiente de teste - mas o problema é que um backup completo seria muito grande e não preciso que todas as tabelas sejam atualizadas, apenas algumas- e também os usuários e a segurança no banco de dados de produção são diferentes de teste. Isso seria substituído pelas configurações de segurança no banco de dados de produção se eu restaurar o banco de dados inteiro.

Eric Larson
fonte
Também vale a pena investigar esta abordagem: sqlperformance.com/2012/08/t-sql-queries/… e sqlperformance.com/2013/04/t-sql-queries/…
Aaron Bertrand

Respostas:

4

Existem 2 métodos que atenderão às suas necessidades:

(Nota: Se as tabelas forem referenciadas por chave estrangeira, você não poderá usá-lo TRUNCATE. É necessário excluir em pedaços . Como alternativa, você pode eliminar todos os índices + Chaves estrangeiras e carregar dados e, em seguida, recriá-los).

  • BCP OUT e BULK INSERT INTO no banco de dados de destino .

    • Coloque o banco de dados de teste no modo de recuperação simples / registrado em massa.
    • Ativar sinalizador de rastreamento 610 - inserções minimamente registradas em tabelas indexadas.

      /************************************************************************************************************************************************
      Author      :   KIN SHAH    *********************************************************************************************************************
      Purpose     :   Move data from one server to another*********************************************************************************************
      DATE        :   05-28-2013  *********************************************************************************************************************
      Version     :   1.0.0   *************************************************************************************************************************
      RDBMS       :   MS SQL Server 2008R2 and 2012   *************************************************************************************************
      *************************************************************************************************************************************************/
      
      -- save below output in a bat file by executing below in SSMS in TEXT mode
      -- clean up: create a bat file with this command --> del D:\BCP_OUT\*.dat 
      
      select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" '-- path to BCP.exe
              +  QUOTENAME(DB_NAME())+ '.'                                    -- Current Database
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
              +  QUOTENAME(name)  
              +  ' out D:\BCP_OUT\'                                           -- Path where BCP out files will be stored
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
              +  REPLACE(name,' ','') 
              + '.dat -T -E -SSERVERNAME\INSTANCE -n'                         -- ServerName, -E will take care of Identity, -n is for Native Format
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'                       -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'                     -- Optional to exclude any schema 
      order by schema_name(schema_id)                         
      
      
      
      --- Execute this on the destination server.database from SSMS.
      --- Make sure the change the @Destdbname and the bcp out path as per your environment.
      
      declare @Destdbname sysname
      set @Destdbname = 'destination_database_Name'               -- Destination Database Name where you want to Bulk Insert in
      select 'BULK INSERT '                                       -- Remember Tables **must** be present on destination Database
              +  QUOTENAME(@Destdbname)+ '.'
              +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.' 
              +  QUOTENAME(name) 
              + ' from ''D:\BCP_OUT\'                             -- Change here for bcp out path
              +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'
              +  REPLACE(name,' ','') 
              +'.dat'' 
              with (
              KEEPIDENTITY,
              DATAFILETYPE = ''native'',  
              TABLOCK
              )'  + char(10) 
              + 'print ''Bulk insert for '+REPLACE(SCHEMA_NAME(schema_id),' ','') + '_'+  REPLACE(name,' ','')+' is done... '''+ char(10)+'go' 
      from sys.tables
      where is_ms_shipped = 0 and name <> 'sysdiagrams'           -- sysdiagrams is classified my MS as UserTable and we dont want it
      and schema_name(schema_id) <> 'some_schema_exclude'         -- Optional to exclude any schema 
      order by schema_name(schema_id)

-

  • Método 2: SSIS - Meu método preferido neste caso.

    • Não é necessário armazenamento temporário no disco. Todo o processamento é feito na memória.
    • Você pode agendar o pacote SSIS usando o trabalho do agente sql todos os meses para automatizar a atualização de tabelas do PROD para o servidor TEST.
    • Escolha a opção " FAST LOAD "
    • Certifique-se de escolher boas linhas por número de lote (se você escolher muito alto, haverá escalonamento de bloqueios - mantenha-o abaixo de 5K)

Referência: O Guia de Desempenho para Carregamento de Dados e minha resposta para - Inserir na tabela selecione * da tabela versus inserção em massa

Kin Shah
fonte
1
O SSIS é definitivamente o caminho a percorrer aqui. O bombeamento de dados é o que foi projetado para fazer.
Steve Mangiameli
3

Não há necessidade de fazer backups e restaurações, ou chamar / coordenar processos externos (por exemplo, BCP), ou mesmo mexer com o SSIS (muito poderoso, muito legal, mas se eu puder evitá-lo, certamente o farei :). Você pode lidar com tudo isso no conforto do T-SQL, em um procedimento armazenado que você pode agendar via SQL Agent ou em um script que você executa uma vez por mês (embora tê-lo em um proc e agendamento seja menos trabalhoso no longo prazo) corre). Quão? O uso do SQLCLR para acessar a classe cuida de quase tudo para você (você pode definir o tamanho do lote, acionar ou não gatilhos, etc.). Ou, se você não quiser mexer na compilação e implantação de um Assembly, poderá usar um procedimento armazenado SQLCLR pré-criado, como DB_BulkCopy, que faz parte do SQL #SqlBulkCopy classe no .NET, ela é essencialmente o BCP sem todo o barulho de chamar o BCP. Você pode codificar isso sozinho: não há uma configuração super complicada nem nada como oSqlBulkCopy biblioteca SQLCLR (da qual sou o autor, mas que está armazenado). procedimento está na versão gratuita). Descrevo isso com mais detalhes, incluindo um exemplo do uso de DB_BulkCopy , na seguinte resposta:

Importar dados de um banco de dados para outro script

Se não estiver claro onde colocar isso em seu plano atual, faça o seguinte:

  • Remova as etapas 1 e 2 (woo hoo!)
  • Substitua a etapa 5 por uma EXECde DB_BulkCopy ou o que você chamar, se você codificar por si mesmo, que apenas move os dados do ponto A para o ponto B.

Além disso, deve-se salientar que SqlBulkCopye DB_BulkCopy :

  • pode aceitar qualquer conjunto de resultados: não importa se é um SELECT ou EXEC de um procedimento armazenado
  • são muito fáceis de atualizar quando são feitas alterações de esquema em qualquer uma dessas tabelas; basta ALTERAR a consulta no Procedimento Armazenado que chama este Procedimento Armazenado SQLCLR
  • permitir remapear os campos, se isso for necessário

ATUALIZAÇÃO sobre operações registradas minimamente via SqlBulkCopy

É possível obter operações minimamente registradas, mas você deve saber:

  • Você precisa usar a opção Cópia em massa do TableLock
  • Para isso, para tabelas com índices clusterizados, primeiro carregue os dados [tempdb]e depois faça a inserção ordenada no destino. Portanto, há uma carga adicional incorrida, tanto em termos de E / S física para tempdb (arquivos de dados e log) quanto na operação de classificação (devido ao ORDER BYque é necessário para obter as operações minimamente registradas)
  • Alguns resultados dos testes aqui: White paper: desempenho do SqlBulkCopy
  • Alguns resultados de teste aqui: Solucionando problemas do SqlBulkCopy não executando o log mínimo
Solomon Rutzky
fonte