sql >> Databasteknik >  >> RDS >> Sqlserver

Hur optimerar jag Upsert (Uppdatera och infoga) operation i SSIS-paketet?

Exempelpaket med SSIS 2008 R2 som infogar eller uppdaterar med batchoperation:

Här är ett exempelpaket skrivet i SSIS 2008 R2 som illustrerar hur man utför infogning, uppdatering mellan två databaser med batchoperationer.

  • Med OLE DB Command kommer att sakta ner uppdateringsoperationerna på ditt paket eftersom det inte gör det utföra batchoperationer. Varje rad uppdateras individuellt.

Exemplet använder två databaser nämligen Source och Destination . I mitt exempel finns båda databaserna på servern men logiken kan fortfarande tillämpas för databaser som finns på olika servrar och platser.

Jag skapade en tabell med namnet dbo.SourceTable i min källdatabas Source .

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

Dessutom skapade två tabeller med namnet dbo.DestinationTable och dbo.StagingTable i min destinationsdatabas 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

Infogade cirka 1,4 miljoner rader i tabellen dbo.SourceTable med unika värden till RowNumber kolumn. Tabellerna dbo.DestinationTable och dbo.StagingTable var tomma till att börja med. Alla rader i tabellen dbo.SourceTable ha flaggan IsActive inställd på false.

Skapat ett SSIS-paket med två OLE DB-anslutningshanterare, som var och en ansluter till Source och Destination databaser. Designade kontrollflödet som visas nedan:

  • Första Execute SQL Task kör satsen TRUNCATE TABLE dbo.StagingTable mot destinationsdatabasen för att trunkera mellanlagringstabellerna.

  • Nästa avsnitt förklarar hur Data Flow Task är konfigurerad.

  • Andra Execute SQL Task kör nedanstående SQL-sats som uppdaterar data i dbo.DestinationTable använda den information som är tillgänglig i dbo.StagingTable , förutsatt att det finns en unik nyckel som matchar mellan dessa två tabeller. I det här fallet är den unika nyckeln kolumnen RowNumber .

Skript att uppdatera:

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

Jag har utformat dataflödesuppgiften som visas nedan.

  • OLE DB Source läser data från dbo.SourceTable med SQL-kommandot SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation används för att kontrollera om RowNumber-värdet redan finns i tabellen dbo.DestinationTable

  • Om posten inte gör det existerar, kommer den att omdirigeras till OLE DB Destination heter Insert into destination table , som infogar raden i dbo.DestinationTable

  • Om posten finns , kommer den att omdirigeras till OLE DB Destination namnges som Insert into staging table , som infogar raden i dbo.StagingTable . Dessa data i staging-tabellen kommer att användas i den andra `Kör SQL-uppgiften för att utföra batchuppdatering.

För att aktivera några fler rader för OLE DB Source, körde jag frågan nedan för att aktivera några poster

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

Första körningen av paketet såg ut som visas nedan. Alla rader dirigerades till destinationstabellen eftersom den var tom. Exekveringen av paketet på min maskin tog ungefär 3 seconds .

Kör radräkningsfrågan igen för att hitta radantalet i alla tre tabellerna.

För att aktivera några fler rader för OLE DB Source, körde jag frågan nedan för att aktivera några poster

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

Andra körningen av paketet såg ut som visas nedan. 314,268 rows som tidigare infogades under den första körningen omdirigerades till mellanställningstabellen. 628,766 new rows infogades direkt i destinationstabellen. Exekveringen av paketet på min maskin tog ungefär 12 seconds . 314,268 rows i destinationstabellen uppdaterades i den andra Execute SQL-uppgiften med data med hjälp av staging-tabellen.

Kör radräkningsfrågan igen för att hitta radantalet i alla tre tabellerna.

Jag hoppas att det ger dig en idé om hur du kan implementera din lösning.



  1. MySQL MyISAM slow count()-fråga trots att det täcker index

  2. Kapslad fråga i squeel

  3. PostgreSQL 9.3:Dynamisk pivottabell

  4. SQLiteException med WHERE +KEY_Date+='+date+'