このリンクを参照してください: MERGEステートメントのパフォーマンスの最適化
理想的なパフォーマンスのために、次の基準が与えられています。
定期的に100万から500万の行をマージする大きなテーブル(1億行以上)がたくさんあります。ターゲットテーブルには一意のクラスター化インデックスがあり、ソーステーブルのキーと一致し、2番目の基準を満たしています。
時間の経過とともにソーステーブルにデータを入力する一括インポートプロセスがあります。次に、マージの準備として、non-uniqueクラスター化インデックスを配置します-これは、重複する値が挿入されないようにする方法がないためですバルクプロセス中。これは半分だけが最初の基準を満たします。
マージのソースとして重複排除ロジックを備えたCTEを使用しています-
...
USING
( SELECT
cte.Key1,
cte.Key2,
cte.Key3,
cte.RestOfTheColumns
FROM
( SELECT
Key1,
Key2,
Key3,
RestOfTheColumns,
,ROW_NUMBER() OVER (PARTITION BY Key1, Key2, Key3 ORDER BY Key1, Key2, Key3) AS RowNumber
) cte
WHERE cte.RowNumber = 1
)
...
理想的には、これは一意にインデックス付けされたテーブルにすでに存在していると思います。
要約すれば:
CTE /基礎となるテーブルに明示的な一意の制約がないことは重要ですか?重複はありませんが、SQLはそれを認識していないため、アップサートのすべての行をチェックすると思います。
CTEがクエリを実行しているテーブルに(Key1、Key2、Key3、...)で始まるクラスター化(またはカバー)インデックスがある場合、これはパフォーマンスの高いクエリである必要があります。
ソーステーブルの「Key4」(できればID列)を一意でないクラスター化インデックスに追加して、インデックスを一意にすることができますか?そうすれば、ROW_NUMBER()
の_ORDER BY
_として「Key4」を設定することもできます。これかもしれないパフォーマンスを改善しますが、それは単なる推測です。
Clustered Index Merge演算子がプランの90%を超えているという事実は、それ自体がパフォーマンスの問題を示しているわけではなく、結合以外にクエリプランで行うことはそれほど多くないことを示しています。実際、十分に最適化された計画があることを示している可能性があります。適切なインデックスがある場合、ROW_NUMBER()
は非常に効率的です。