sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan optimerer jeg Upsert (Opdater og Indsæt) drift i SSIS-pakken?

Eksempelpakke ved hjælp af SSIS 2008 R2, der indsætter eller opdaterer ved hjælp af batch-handling:

Her er en prøvepakke skrevet i SSIS 2008 R2 der illustrerer, hvordan man udfører indsættelse, opdatering mellem to databaser ved hjælp af batch-operationer.

  • Ved brug af OLE DB Command vil sænke opdateringshandlingerne på din pakke, fordi den ikke gør udføre batch-operationer. Hver række opdateres individuelt.

Eksemplet bruger to databaser, nemlig Source og Destination . I mit eksempel ligger begge databaser på serveren, men logikken kan stadig anvendes for databaser, der ligger på forskellige servere og steder.

Jeg oprettede en tabel med navnet dbo.SourceTable i min kildedatabase Source .

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

Også oprettet to tabeller med navnet dbo.DestinationTable og dbo.StagingTable i min destinationsdatabase 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

Indsatte omkring 1,4 millioner rækker i tabellen dbo.SourceTable med unikke værdier i RowNumber kolonne. Tabellerne dbo.DestinationTable og dbo.StagingTable var tomme til at begynde med. Alle rækkerne i tabellen dbo.SourceTable har flaget IsActive indstillet til falsk.

Oprettet en SSIS-pakke med to OLE DB-forbindelsesadministratorer, der hver forbinder til Source og Destination databaser. Designede kontrolflowet som vist nedenfor:

  • Første Execute SQL Task udfører sætningen TRUNCATE TABLE dbo.StagingTable mod destinationsdatabasen for at afkorte iscenesættelsestabellerne.

  • Næste afsnit forklarer, hvordan Data Flow Task er konfigureret.

  • Anden Execute SQL Task udfører nedenstående SQL-sætning, der opdaterer data i dbo.DestinationTable ved hjælp af de tilgængelige data i dbo.StagingTable , forudsat at der er en unik nøgle, der matcher mellem disse to tabeller. I dette tilfælde er den unikke nøgle kolonnen RowNumber .

Script til opdatering:

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

Jeg har designet dataflowopgaven som vist nedenfor.

  • OLE DB Source læser data fra dbo.SourceTable ved hjælp af SQL-kommandoen SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation bruges til at kontrollere, om RowNumber-værdien allerede findes i tabellen dbo.DestinationTable

  • Hvis posten ikke eksisterer, vil den blive omdirigeret til OLE DB Destination navngivet som Insert into destination table , som indsætter rækken i dbo.DestinationTable

  • Hvis posten findes , vil den blive omdirigeret til OLE DB Destination navngivet som Insert into staging table , som indsætter rækken i dbo.StagingTable . Disse data i staging-tabellen vil blive brugt i den anden `Udfør SQL-opgave for at udføre batchopdatering.

For at aktivere nogle flere rækker til OLE DB Source, kørte jeg nedenstående forespørgsel for at aktivere nogle poster

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

Første udførelse af pakken så ud som vist nedenfor. Alle rækkerne blev dirigeret til destinationstabel, fordi den var tom. Udførelsen af ​​pakken på min maskine tog omkring 3 seconds .

Kørte rækkeoptællingsforespørgslen igen for at finde rækkeantallet i alle tre tabeller.

For at aktivere nogle flere rækker til OLE DB Source, kørte jeg nedenstående forespørgsel for at aktivere nogle poster

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

Anden udførelse af pakken så ud som vist nedenfor. 314,268 rows som tidligere blev indsat under den første udførelse blev omdirigeret til staging table. 628,766 new rows blev direkte indsat i destinationstabellen. Udførelsen af ​​pakken på min maskine tog omkring 12 seconds . 314,268 rows i destinationstabel blev opdateret i den anden Execute SQL Task med dataene ved hjælp af staging table.

Kørte rækkeantallet igen for at finde rækkeantallet i alle tre tabeller.

Jeg håber, det giver dig en idé til at implementere din løsning.



  1. Brug af indbygget sql-konverteringsfunktion i nhibernate-kriterier

  2. XPath for at hente SQL XML-værdi

  3. ROW_NUMBER forespørgsel

  4. Få ID'et for de sidst indsatte poster