0

SQL Server 2008 R2 に次の形式のクエリがあります。

SELECT TOP (2147483647) *
FROM (
    SELECT *
    FROM sub_query_a
) hierarchy
LEFT JOIN (
    SELECT *
    FROM sub_query_b
) expenditure
ON hierarchy.x = expenditure.x AND hierarchy.y = expenditure.y
ORDER BY hierarchy.c, hierarchy.d, hierarchy.e

hierarchyサブクエリには UNIONS と INNER JOINS が含まれています。サブクエリは、いくつかのレベルのexpenditureサブサブクエリに基づいており、UNIONS、INNER、LEFT JOINS、および最終的に PIVOT 集計を含みます。

hierarchyサブクエリ自体は 2 秒で実行され、467 行が返されます。expenditureサブクエリ自体は 7 秒で実行され、458 行が返されます。一緒に、句なしで、クエリは 11 秒で実行されます。ORDER BYただし、句を使用すると、クエリは 11 分で実行さますORDER BY

実際の実行計画は、何が違うかを明らかにします。ORDER BY節がない場合、サブクエリhierarchyexpenditureサブクエリの両方がそれぞれ 1 回実行され、結果がMerge Join (Right Outer Join)結合されます。ORDER BY句が含まれている場合hierarchyでもクエリは 1 回実行されますが、そのexpenditure部分は階層クエリから行ごとに 1 回実行され、結果がNested Loops (Left Outer Join)結合されます。そのORDER BY句がexpenditureサブクエリを相関サブクエリにさせているかのようです(そうではありません)。

テストとして、SQL Server が実際にクエリを実行し、並べ替えられた結果セットを 11 秒で生成できることを確認するために、一時テーブルを作成し、句なしでクエリの結果を挿入しました。ORDER BYそれから私はしましたSELECT * FROM #temp_table ORDER BY c, d, e。スクリプト全体で予想どおり 11 秒かかり、必要な結果が返されました。

句を 1 つのクエリとして使用してクエリを効率的ORDER BYに機能させたい - #temp_table ハック ソリューションを有効にするためだけにストアド プロシージャを作成する必要はありません。

この問題の原因、または修正に関するアイデアはありますか?

4

2 に答える 2

1

optionネストされたループ結合を避けるために、コンパイラにを与えることができます:

SELECT TOP (2147483647) *
FROM (
    SELECT *
    FROM sub_query_a
) hierarchy
LEFT JOIN (
    SELECT *
    FROM sub_query_b
) expenditure
ON hierarchy.x = expenditure.x AND hierarchy.y = expenditure.y
ORDER BY hierarchy.c, hierarchy.d, hierarchy.e
option (merge join, hash join)

私は通常、オプティマイザーに正しいクエリ プランを見つけてもらうことを好みます。ただし、まれに、あなたと同様の問題に遭遇し、正しい方向に進めるための提案をする必要があります

于 2013-06-13T16:57:24.080 に答える