SQL Server 2008 R2クエリオプティマイザーパズル
2つのテーブルがあり、どちらにも900万行が含まれています。70.000行は異なり、他は同じです。
これは高速、13秒です。
select * from bigtable1
except select * from similar_bigtable2
これにより出力がソートされ、13秒も高速になります。
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
これは非常に遅いですが、
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
そして、クエリの特定の部分を事前に計算する必要があることをSQL Serverに示唆するために時々使用する「トリック」でさえ、機能せず、クエリが遅くなります。
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
クエリプランを見ると、理由を見つけるのは難しくありません。
SQL Server は、ハッシュ一致の前に 2種類の900万行を配置しますが、ハッシュ一致の後に 1種類の70.000行のみを追加することをお勧めします。
質問:クエリオプティマイザーにそのように指示するにはどうすればよいですか?
EXCEPT
(例OUTER JOIN
)に代わるものを試しましたか?構文はあまり便利ではありませんが、そこでインデックス/結合のヒントをよりうまく使用できる場合があります(または必要がない場合もあります)。現在使用している代替手段(#tempテーブルに最初に入れるもの)は最後の回避策ですが、場合によっては、オプティマイザーに希望する方法でクエリの2つの部分を完全に分離させる唯一の方法です。