私はいくつかのテーブルを結合し、かなり悪いパフォーマンスを発揮するクエリを持っています-行の推定はかなり(1000回)オフであり、ネストされたループ結合が選択され、複数のテーブルスキャンが発生します。クエリの形状は非常に単純で、次のようになります。
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
クエリをいじると、結合の1つにMerge結合を使用するようにヒントを出すと、実行が何倍も速くなることに気付きました。これは理解できます-結合結合は、結合されるデータにとってより良いオプションですが、SQL Serverはネストされたループを選択するだけでは正しく推定しません。
私が完全に理解していないのは、この結合ヒントがすべてのプラン演算子のすべての推定値を変更する理由です。さまざまな記事や本を読んで、計画を構築する前にカーディナリティの推定が実行されると想定したため、ヒントを使用しても推定は変更されず、SQL Serverに特定の物理結合実装を使用するよう明示的に指示します。
ただし、Mergeヒントを使用すると、すべての推定がほぼ完璧になります。なぜこれが起こるのか、ヒントなしでクエリオプティマイザーがより良い推定を行う一般的な手法はありますか?統計が明らかにこれを許可していることを考慮して?
UPD:匿名化された実行計画はここにあります:https : //www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan ? dl = 0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
TF 3604、9202、9204を使用して両方のクエリで使用される統計情報を確認しましたが、これらは同じです。ただし、スキャン/シークされるインデックスはクエリによって異なります。
それに加えて、クエリを実行しようとしましたOPTION (FORCE ORDER)
-マージ結合を使用するよりも速く実行され、すべての結合にHASH MATCHを選択します。