sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo optimizo la operación Upsert (Actualizar e Insertar) dentro del paquete SSIS?

Paquete de muestra con SSIS 2008 R2 que se inserta o actualiza mediante operación por lotes:

Aquí hay un paquete de muestra escrito en SSIS 2008 R2 que ilustra cómo realizar la inserción, actualizar entre dos bases de datos utilizando operaciones por lotes.

  • Usando OLE DB Command ralentizará las operaciones de actualización en su paquete porque no realizar operaciones por lotes. Cada fila se actualiza individualmente.

El ejemplo utiliza dos bases de datos, a saber, Source y Destination . En mi ejemplo, ambas bases de datos residen en el servidor, pero la lógica aún se puede aplicar para las bases de datos que residen en diferentes servidores y ubicaciones.

Creé una tabla llamada dbo.SourceTable en mi base de datos fuente Source .

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

Además, creó dos tablas llamadas dbo.DestinationTable y dbo.StagingTable en mi base de datos 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

Insertado alrededor de 1,4 millones de filas en la tabla dbo.SourceTable con valores únicos en RowNumber columna. Las tablas dbo.DestinationTable y dbo.StagingTable estaban vacíos para empezar. Todas las filas de la tabla dbo.SourceTable tener la bandera IsActive establecido en falso.

Creó un paquete SSIS con dos administradores de conexión OLE DB, cada uno conectado a Source y Destination bases de datos Diseñó el flujo de control como se muestra a continuación:

  • Primero Execute SQL Task ejecuta la sentencia TRUNCATE TABLE dbo.StagingTable contra la base de datos de destino para truncar las tablas provisionales.

  • La siguiente sección explica cómo la Data Flow Task está configurado.

  • Segundo Execute SQL Task ejecuta la instrucción SQL dada a continuación que actualiza los datos en dbo.DestinationTable usando los datos disponibles en dbo.StagingTable , asumiendo que hay una clave única que coincide entre esas dos tablas. En este caso, la clave única es la columna RowNumber .

Script para actualizar:

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

He diseñado la tarea de flujo de datos como se muestra a continuación.

  • OLE DB Source lee datos de dbo.SourceTable usando el comando SQL SELECT RowNumber,CreatedOn, ModifiedOn FROM Source.dbo.SourceTable WHERE IsActive = 1

  • Lookup transformation se utiliza para verificar si el valor RowNumber ya existe en la tabla dbo.DestinationTable

  • Si el registro no existe, será redirigido al OLE DB Destination nombrado como Insert into destination table , que inserta la fila en dbo.DestinationTable

  • Si el registro existe , será redirigido al OLE DB Destination nombrado como Insert into staging table , que inserta la fila en dbo.StagingTable . Estos datos en la tabla de preparación se utilizarán en la segunda `Ejecutar tarea de SQL para realizar la actualización por lotes.

Para activar algunas filas más para OLE DB Source, ejecuté la siguiente consulta para activar algunos registros

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

La primera ejecución del paquete se veía como se muestra a continuación. Todas las filas se dirigieron a la tabla de destino porque estaba vacía. La ejecución del paquete en mi máquina tomó alrededor de 3 seconds .

Ejecutó la consulta de recuento de filas nuevamente para encontrar los recuentos de filas en las tres tablas.

Para activar algunas filas más para OLE DB Source, ejecuté la siguiente consulta para activar algunos registros

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

La segunda ejecución del paquete se veía como se muestra a continuación. 314,268 rows que se insertaron previamente durante la primera ejecución se redirigieron a la tabla de preparación. 628,766 new rows se insertaron directamente en la tabla de destino. La ejecución del paquete en mi máquina tomó alrededor de 12 seconds . 314,268 rows en la tabla de destino se actualizaron en la segunda tarea Ejecutar SQL con los datos usando la tabla de preparación.

Ejecutó la consulta de recuento de filas nuevamente para encontrar los recuentos de filas en las tres tablas.

Espero que eso le dé una idea para implementar su solución.