Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment optimiser l'opération Upsert (mise à jour et insertion) dans le package SSIS ?

Exemple de package utilisant SSIS 2008 R2 qui insère ou met à jour à l'aide d'une opération par lots :

Voici un exemple de package écrit en SSIS 2008 R2 qui illustre comment effectuer une insertion, une mise à jour entre deux bases de données à l'aide d'opérations par lots.

  • Utilisation de la OLE DB Command ralentira les opérations de mise à jour sur votre paquet parce qu'il ne le fait pas effectuer des opérations par lots. Chaque ligne est mise à jour individuellement.

L'exemple utilise deux bases de données à savoir Source et Destination . Dans mon exemple, les deux bases de données résident sur le serveur, mais la logique peut toujours être appliquée pour les bases de données résidant sur des serveurs et des emplacements différents.

J'ai créé une table nommée dbo.SourceTable dans ma base de données source Source .

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

Également créé deux tables nommées dbo.DestinationTable et dbo.StagingTable dans ma base de données de destination 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

Insertion d'environ 1,4 million de lignes dans la table dbo.SourceTable avec des valeurs uniques dans RowNumber colonne. Les tables dbo.DestinationTable et dbo.StagingTable étaient vides au départ. Toutes les lignes de la table dbo.SourceTable avoir le drapeau IsActive défini sur faux.

Création d'un package SSIS avec deux gestionnaires de connexions OLE DB, chacun se connectant à Source et Destination bases de données. Concevez le flux de contrôle comme indiqué ci-dessous :

  • Premier Execute SQL Task exécute l'instruction TRUNCATE TABLE dbo.StagingTable par rapport à la base de données de destination pour tronquer les tables intermédiaires.

  • La section suivante explique comment la Data Flow Task est configuré.

  • Deuxième Execute SQL Task exécute l'instruction SQL ci-dessous qui met à jour les données dans dbo.DestinationTable en utilisant les données disponibles dans dbo.StagingTable , en supposant qu'il existe une clé unique qui correspond entre ces deux tables. Dans ce cas, la clé unique est la colonne RowNumber .

Script à mettre à jour :

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

J'ai conçu la tâche de flux de données comme indiqué ci-dessous.

  • OLE DB Source lit les données de dbo.SourceTable en utilisant la commande SQL SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation est utilisé pour vérifier si la valeur RowNumber existe déjà dans la table dbo.DestinationTable

  • Si l'enregistrement ne le fait pas existe, il sera redirigé vers la OLE DB Destination nommé comme Insert into destination table , qui insère la ligne dans dbo.DestinationTable

  • Si l'enregistrement existe , il sera redirigé vers la OLE DB Destination nommé comme Insert into staging table , qui insère la ligne dans dbo.StagingTable . Ces données dans la table intermédiaire seront utilisées dans la deuxième `Exécuter la tâche SQL pour effectuer la mise à jour par lots.

Pour activer quelques lignes supplémentaires pour la source OLE DB, j'ai exécuté la requête ci-dessous pour activer certains enregistrements

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

La première exécution du package s'est déroulée comme indiqué ci-dessous. Toutes les lignes ont été dirigées vers la table de destination car elle était vide. L'exécution du package sur ma machine a pris environ 3 seconds .

Exécutez à nouveau la requête de nombre de lignes pour trouver le nombre de lignes dans les trois tables.

Pour activer quelques lignes supplémentaires pour la source OLE DB, j'ai exécuté la requête ci-dessous pour activer certains enregistrements

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

La deuxième exécution du package s'est déroulée comme indiqué ci-dessous. 314,268 rows précédemment insérés lors de la première exécution ont été redirigés vers la table intermédiaire. 628,766 new rows ont été directement insérés dans la table de destination. L'exécution du package sur ma machine a pris environ 12 seconds . 314,268 rows dans la table de destination ont été mis à jour dans la deuxième tâche d'exécution SQL avec les données à l'aide de la table intermédiaire.

Exécutez à nouveau la requête de nombre de lignes pour trouver le nombre de lignes dans les trois tables.

J'espère que cela vous donne une idée pour mettre en œuvre votre solution.