sql >> データベース >  >> RDS >> Sqlserver

SSIS パッケージ内で Upsert (更新と挿入) 操作を最適化するにはどうすればよいですか?

    バッチ操作を使用して挿入または更新する SSIS 2008 R2 を使用するサンプル パッケージ:

    SSIS 2008 R2 で書かれたサンプル パッケージを次に示します。 これは、バッチ操作を使用して 2 つのデータベース間で挿入、更新を実行する方法を示しています。

    • OLE DB Commandの使用 しないため、パッケージの更新操作が遅くなります バッチ操作を実行します。すべての行が個別に更新されます。

    このサンプルでは、​​Source という 2 つのデータベースを使用します。 そして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 という名前の 2 つのテーブルを作成しました および 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
    

    テーブル dbo.SourceTable に約 140 万行を挿入 RowNumber に一意の値を持つ 桁。テーブル dbo.DestinationTable および dbo.StagingTable 最初から空でした。テーブル内のすべての行 dbo.SourceTable フラグ IsActive を持っている false に設定します。

    それぞれが Source に接続する 2 つの OLE DB 接続マネージャーを含む SSIS パッケージを作成しました および Destination データベース。以下に示すように制御フローを設計しました:

      <リ>

      最初の Execute SQL Task ステートメント TRUNCATE TABLE dbo.StagingTable を実行します 宛先データベースに対してステージング テーブルを切り捨てます。

      <リ>

      次のセクションでは、Data Flow Task

      <リ>

      2 番目の Execute SQL Task dbo.DestinationTable のデータを更新する以下の SQL ステートメントを実行します dbo.StagingTable で利用可能なデータを使用する 、これら 2 つのテーブル間で一致する一意のキーがあると仮定します。この場合、一意のキーは列 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 に挿入します .ステージング テーブルのこのデータは、2 番目の `SQL 実行タスクで使用され、バッチ更新を実行します。

    OLE DB ソース用にさらにいくつかの行をアクティブ化するために、以下のクエリを実行していくつかのレコードをアクティブ化しました

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

    パッケージの最初の実行は、次のように表示されます。宛先テーブルが空だったため、すべての行が宛先テーブルに送られました。私のマシンでのパッケージの実行には、約 3 seconds かかりました .

    行数クエリを再度実行して、3 つのテーブルすべての行数を確認してください。

    OLE DB ソース用にさらにいくつかの行をアクティブ化するために、以下のクエリを実行していくつかのレコードをアクティブ化しました

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

    パッケージの 2 回目の実行は、次のようになります。 314,268 rows 最初の実行時に以前に挿入されたものは、ステージング テーブルにリダイレクトされました。 628,766 new rows 宛先テーブルに直接挿入されました。私のマシンでのパッケージの実行には、約 12 seconds かかりました . 314,268 rows ステージング テーブルを使用して、2 番目の SQL 実行タスクで宛先テーブルのデータが更新されました。

    行数クエリを再度実行して、3 つのテーブルすべての行数を確認してください。

    ソリューションを実装するためのアイデアが得られることを願っています。



    1. OracleのCAST()関数

    2. Oraclesqlldrタイムスタンプ形式の頭痛の種

    3. Oracleのオプションの関係

    4. MYSQLは、トランザクション内のダンプファイルをすべてまたはまったく再生しません