検索値が交換されるとパフォーマンスが大幅に低下するデュアル自己結合クエリがあります。
-- 500,000 i/o & 500ms execution
select
fooA.ID
, fooB.ID
from
foo AS fooA
INNER JOIN bar AS barA ON fooA.barID = barA.barID
INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join
INNER JOIN bar AS barB ON fooB.barID = barB.barID
where
barA.value = 'xyz'
AND barB.value = '60'
-- 5,000 i/o & 5ms execution
select
fooA.ID
, fooB.ID
from
foo AS fooA
INNER JOIN bar AS barA ON fooA.barID = barA.barID
INNER JOIN foo AS fooB ON fooA.fooID = fooB.fooID -- self join
INNER JOIN bar AS barB ON fooB.barID = barB.barID
where
barA.value = '60'
AND barB.value = 'xyz'
- 値「xyz」は、「バー」テーブルに150,000回リストされています。
- 値「60」は「バー」テーブルに500回リストされています。
- クエリプランは同じですが、最も内側のループが最初にリストされている検索値に応じて150,000行または500行を返す点が異なります。
- 検索は、非クラスター化インデックスでシークを実行します。
- 統計は、FULLSCANを使用して両方のテーブルで更新されました。
SQLクエリオプティマイザが、両方のインスタンスでクエリプランの最も内側の結合が行数が最も少ない結合であることを正しく識別しないのはなぜですか?