Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да оптимизирам операцията Upsert (Актуализиране и вмъкване) в рамките на пакета SSIS?

Примерен пакет, използващ SSIS 2008 R2, който вмъква или актуализира чрез групова операция:

Ето примерен пакет, написан на SSIS 2008 R2 който илюстрира как да се извърши вмъкване, актуализиране между две бази данни чрез пакетни операции.

  • Използване на OLE DB Command ще забави операциите за актуализиране на вашия пакет, защото не извършване на групови операции. Всеки ред се актуализира индивидуално.

Примерът използва две бази данни, а именно Source и Destination . В моя пример и двете бази данни се намират на сървъра, но логиката все още може да се приложи за бази данни, намиращи се на различни сървъри и местоположения.

Създадох таблица с име dbo.SourceTable в моята база данни източник Source .

CREATE TABLE [dbo].[SourceTable](
    [RowNumber] [bigint] NOT NULL,
    [CreatedOn] [datetime] NOT NULL,
    [ModifiedOn] [datetime] NOT NULL,
    [IsActive] [bit] NULL
)

Освен това създаде две таблици с име dbo.DestinationTable и dbo.StagingTable в моята база данни за местоназначение 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

Вмъкнати са около 1,4 милиона реда в таблицата dbo.SourceTable с уникални стойности в RowNumber колона. Таблиците dbo.DestinationTable и dbo.StagingTable бяха празни в началото. Всички редове в таблицата dbo.SourceTable имат флаг IsActive зададено на false.

Създаден SSIS пакет с два мениджъра на OLE DB връзки, всеки от които се свързва към Source и Destination бази данни. Проектира контролния поток, както е показано по-долу:

  • Първо Execute SQL Task изпълнява израза TRUNCATE TABLE dbo.StagingTable срещу целевата база данни, за да отрежете междинните таблици.

  • Следващият раздел обяснява как Data Flow Task е конфигуриран.

  • Второ Execute SQL Task изпълнява дадения по-долу SQL оператор, който актуализира данните в dbo.DestinationTable използвайки наличните данни в dbo.StagingTable , като се приеме, че има уникален ключ, който съвпада между тези две таблици. В този случай уникалният ключ е колоната RowNumber .

Скрипт за актуализиране:

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

Проектирах задачата за поток от данни, както е показано по-долу.

  • OLE DB Source чете данни от dbo.SourceTable използвайки SQL командата SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation се използва за проверка дали стойността RowNumber вече съществува в таблицата dbo.DestinationTable

  • Ако записната съществува, той ще бъде пренасочен към OLE DB Destination именуван като Insert into destination table , който вмъква реда в dbo.DestinationTable

  • Ако записът съществува , той ще бъде пренасочен към OLE DB Destination именуван като Insert into staging table , който вмъква реда в dbo.StagingTable . Тези данни в междинната таблица ще бъдат използвани във второто `Изпълнение на SQL задача за извършване на пакетна актуализация.

За да активирам още няколко реда за OLE DB източник, изпълних заявката по-долу, за да активирам някои записи

UPDATE  dbo.SourceTable 
SET     IsActive = 1 
WHERE   (RowNumber % 9 = 1) 
OR      (RowNumber % 9 = 2)

Първото изпълнение на пакета изглеждаше както е показано по-долу. Всички редове бяха насочени към целевата таблица, защото беше празна. Изпълнението на пакета на моята машина отне около 3 seconds .

Изпълнете отново заявката за броя на редовете, за да намерите броя на редовете и в трите таблици.

За да активирам още няколко реда за OLE DB източник, изпълних заявката по-долу, за да активирам някои записи

UPDATE  dbo.SourceTable 
SET     IsActive = 1 
WHERE   (RowNumber % 9 = 3) 
OR      (RowNumber % 9 = 5) 
OR      (RowNumber % 9 = 6) 
OR      (RowNumber % 9 = 7)

Второто изпълнение на пакета изглеждаше както е показано по-долу. 314,268 rows които преди това са били вмъкнати по време на първото изпълнение, бяха пренасочени към етапната таблица. 628,766 new rows бяха директно вмъкнати в целевата таблица. Изпълнението на пакета на моята машина отне около 12 seconds . 314,268 rows в целевата таблица бяха актуализирани във втората Изпълнителна SQL задача с данните, използващи етапна таблица.

Изпълнете отново заявката за броя на редовете, за да намерите броя на редовете и в трите таблици.

Надявам се, че това ви дава идея за прилагане на вашето решение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какви са разликите между Merge Join и Lookup трансформациите в SSIS?

  2. GETUTCDATE() Примери в SQL Server (T-SQL)

  3. Избор на географски точки в района

  4. Третирайте колоната като различен тип за сортиране

  5. Изразът GROUP-BY трябва да съдържа поне една колона, която не е външна препратка