Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como otimizar a operação Upsert (Atualizar e Inserir) no pacote SSIS?

Pacote de amostra usando SSIS 2008 R2 que insere ou atualiza usando operação em lote:


Aqui está um pacote de amostra escrito em SSIS 2008 R2 que ilustra como realizar a inserção, atualização entre dois bancos de dados usando operações em lote.
  • Usando o OLE DB Command irá desacelerar as operações de atualização em seu pacote porque não realizar operações em lote. Cada linha é atualizada individualmente.

A amostra usa dois bancos de dados, a saber, Source e Destination . No meu exemplo, ambos os bancos de dados residem no servidor, mas a lógica ainda pode ser aplicada a bancos de dados que residem em servidores e locais diferentes.

Eu criei uma tabela chamada dbo.SourceTable no meu banco de dados de origem Source .
CREATE TABLE [dbo].[SourceTable](
    [RowNumber] [bigint] NOT NULL,
    [CreatedOn] [datetime] NOT NULL,
    [ModifiedOn] [datetime] NOT NULL,
    [IsActive] [bit] NULL
)

Além disso, criou duas tabelas chamadas dbo.DestinationTable e dbo.StagingTable no meu banco de dados de destino Destination .
CREATE TABLE [dbo].[DestinationTable](
    [RowNumber] [bigint] NOT NULL,
    [CreatedOn] [datetime] NOT NULL,
    [ModifiedOn] [datetime] NOT NULL
) 
GO

CREATE TABLE [dbo].[StagingTable](
    [RowNumber] [bigint] NOT NULL,
    [CreatedOn] [datetime] NOT NULL,
    [ModifiedOn] [datetime] NOT NULL
) 
GO

Inseriu cerca de 1,4 milhão de linhas na tabela dbo.SourceTable com valores exclusivos em RowNumber coluna. As tabelas dbo.DestinationTable e dbo.StagingTable estavam vazios para começar. Todas as linhas da tabela dbo.SourceTable tem o sinalizador IsActive definido como falso.



Criou um pacote SSIS com dois gerenciadores de conexões OLE DB, cada um se conectando a Source e Destination bancos de dados. Projetou o Fluxo de Controle conforme mostrado abaixo:

  • Primeiro Execute SQL Task executa a instrução TRUNCATE TABLE dbo.StagingTable no banco de dados de destino para truncar as tabelas de migração de dados.

  • A próxima seção explica como a Data Flow Task está configurado.

  • Segunda Execute SQL Task executa a instrução SQL fornecida abaixo que atualiza os dados em dbo.DestinationTable usando os dados disponíveis em dbo.StagingTable , supondo que haja uma chave exclusiva que corresponda entre essas duas tabelas. Nesse caso, a chave exclusiva é a coluna RowNumber .

Script para atualizar:

UPDATE      D 
SET         D.CreatedOn = S.CreatedOn
        ,   D.ModifiedOn = S.ModifiedOn 
FROM        dbo.DestinationTable D 
INNER JOIN  dbo.StagingTable S 
ON          D.RowNumber = S.RowNumber



Eu projetei a Tarefa de Fluxo de Dados conforme mostrado abaixo.

  • OLE DB Source lê dados de dbo.SourceTable usando o comando SQL SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation é usado para verificar se o valor RowNumber já existe na tabela dbo.DestinationTable

  • Se o registro não existir, ele será redirecionado para o OLE DB Destination nomeado como Insert into destination table , que insere a linha em dbo.DestinationTable

  • Se o registro existir , ele será redirecionado para o OLE DB Destination nomeado como Insert into staging table , que insere a linha em dbo.StagingTable . Esses dados na tabela de preparo serão usados ​​na segunda 'Executar Tarefa SQL para realizar a atualização em lote'.



Para ativar mais algumas linhas para OLE DB Source, executei a consulta abaixo para ativar alguns registros
UPDATE  dbo.SourceTable 
SET     IsActive = 1 
WHERE   (RowNumber % 9 = 1) 
OR      (RowNumber % 9 = 2)



A primeira execução do pacote ficou como mostrado abaixo. Todas as linhas foram direcionadas para a tabela de destino porque estava vazia. A execução do pacote na minha máquina levou cerca de 3 seconds .





Executou a consulta de contagem de linhas novamente para localizar as contagens de linhas em todas as três tabelas.



Para ativar mais algumas linhas para OLE DB Source, executei a consulta abaixo para ativar alguns registros
UPDATE  dbo.SourceTable 
SET     IsActive = 1 
WHERE   (RowNumber % 9 = 3) 
OR      (RowNumber % 9 = 5) 
OR      (RowNumber % 9 = 6) 
OR      (RowNumber % 9 = 7)



A segunda execução do pacote ficou como mostrado abaixo. 314,268 rows que foram inseridos anteriormente durante a primeira execução foram redirecionados para a tabela de preparo. 628,766 new rows foram inseridos diretamente na tabela de destino. A execução do pacote na minha máquina levou cerca de 12 seconds . 314,268 rows na tabela de destino foram atualizados na segunda tarefa Execute SQL com os dados usando a tabela de preparo.





Executou a consulta de contagem de linhas novamente para localizar as contagens de linhas em todas as três tabelas.



Espero que isso lhe dê uma ideia para implementar sua solução.