親子関係のある行を持つテーブルのクエリで問題が発生しました。簡単な例を考えてみると、stackexchange スキーマが非常に似ていることに気付きました。
それで、stackexchange データ エクスプローラーを介して、stackoverflow の投稿テーブルにクエリを実行していると想像してください。すべての投稿とそれに関連する回答のサブセットを取得しようとしています。
サンプル クエリについては、 https://data.stackexchange.com/stackoverflow/query/121981/a-subset-of-questions-and-associated-answersを参照してください。
投稿のサブセットは、かなり複雑でコストのかかるクエリ プランを持つビューで定義されます。以下の例では、単純に上の 2 つの行を選択するように簡略化されています。
ユニオンを使用する最初の方法:
with ExpensiveView as (select top 2 ID from Posts order by ID)
select Posts.*
from ExpensiveView
left outer join Posts
ON ExpensiveView.Id = Posts.Id
union all
select Posts.*
from ExpensiveView
left outer join Posts
ON ExpensiveView.Id = Posts.ParentId
ExpensiveView
は 2 回評価されるため、この方法は避けたいと思います。上記の単純化されたバージョンでは明らかに問題ではありませんが、もう 1 つの複雑なバージョンでは問題が発生します。
2 番目の方法では、条件付き結合句で単一の選択を使用します。
with ExpensiveView as (select top 2 ID from Posts order by ID)
select Posts.*
from ExpensiveView
left outer join Posts
ON ExpensiveView.Id = Posts.Id or ExpensiveView.Id = Posts.ParentId
これにより、2 回評価されることは回避ExpensiveView
されますが、途方もなく大きなクラスター化インデックス スキャンが発生します。IDごとにインデックス全体をスキャンしているようですExpensiveView
(つまり、2 * 14977623 =〜3000万行)。これは非常に遅いです。
2 つの質問
2 番目のクエリの条件付き結合により、インデックス スキャンがこれほど大規模になるのはなぜですか?
ExpensiveView
何度も評価されることなく、探している結果を得る方法はありますか?