12

後続のクエリ(実際には更新ステートメント)で使用する必要がある複雑なクエリがあります。私は両方のCTEと一時テーブルを使用してみました。 CTEを使用したパフォーマンスは、一時テーブルアプローチと比べて恐ろしいものです。 15秒とミリ秒の間の何か。後続のクエリでCTE/Tempテーブルに参加する代わりにテストを簡略化するために、単に*を選択しました。その場合、彼らは同じことを実行します。SQL 2005 CTEとTEMPテーブル他のテーブルの結合で使用された場合のパフォーマンス

私は両方のアプローチの実行計画を、後続のクエリの結合で調べた後、単に*を選択しました。単純な選択では、クエリプランはほぼ同じですが、後続の選択での結合ではクエリプランは作成されません。具体的には、テンポラリテーブルを作成して投入するためのクエリプランの部分は同じままで、CTEを作成して投入するためのクエリプラン部分は、その後、結合を含むクエリで使用されると劇的に変化します。

私の質問は、CTEの作成と作成に関するクエリプランが、一時テーブルが使用されていない間に後でどのように使用されるかによって変更される理由です。また、どのようなシナリオでは、CTEは一時表よりも優れたパフォーマンスを発揮しますか?

注:私もテーブル変数を使用しましたが、これは一時テーブルのアプローチと似ています。

おかげ

答えて

9

あなたは複雑な質問をしているので、複雑な答えを得ています。 (私はその反応が嫌いです)。

しかし、これは、オプティマイザが(すでに知っていた)データプランをどのように選択するかとは関係ありません。一時テーブルまたは変数は、実行計画が最初にその構造を満たすことに関連する操作を実行し、その後の操作でその構造を使用する永続的な構造のようなものです。 CTEは一時表ではありません。 CTEの使用は、後続の操作で使用されるまで計算されないため、計画が最適化される方法に影響を与えます。

CTEは、再利用性とメンテナンスの問題のために実装されています。しかし、多くの場合(再帰のような)、従来のコーディング方法よりも優れたパフォーマンスを発揮します。

13

CTEは、クエリのためだけの別名です。

使用するたびに再実行されることがあります。

あり(Oracleの/*+ MATERIALIZE */など)SQL ServerCTEマテリアを強制するクリーンな方法はありません、あなたはこのような汚い手口行う必要があります:

CTEを使用した場合、パフォーマンスが向上する場合があり(HASH JOINMERGE JOINなどのような)1つの評価だけを必要とする計画では、一時テーブルに結果を引っ張って、再び一時テーブルを読み出し、CTEを評価必要とする一時テーブルを使用しながら、これらのシナリオで

は、ハッシュテーブルは、右CTEから構築されます。

+1

はい、マテリアライズ!定義のPK/IXはいいかもしれません。 – crokusek

2

通常、繰り返されるCTEではパフォーマンスが向上しません。

たとえば、CTEを使用してテーブルを作成し、その後同じクエリを後続のクエリに追加する場合、メリットはありません。残念ながら、CTEはスナップショットではなく、2つの別々のステートメントで使用するためには文字どおり繰り返す必要があるため、2回評価される傾向があります。

CTEではなく、インラインTVF(CTEを含む可能性があります)を使用して、適切な再利用が可能で、SPのCTEよりも優れていたり悪くなったりしません。

また、第1ステップで統計を変更すると、第2ステップの実行計画が常に不正確になる場合、実行計画が悪い可能性があります。これは、ステップが実行される前に評価されるためです。

この場合、中間結果を手動で保存し、適切にインデックスを作成し、複数のSPに分割し、WITH RECOMPILEを追加して、後のSPにはそのデータに適した計画が確実に作成されるようにします実際に作動する予定です。

0

大きなテーブルのフィルタで簡単に選択してCTEを作成しようとしました 次に3回サブクエリしました。

その後、一時テーブルでも同じことをします。

結果は、CTE-70%では時間テーブルの消費時間が30%でした。 そのようなソリューションでは、tempテーブルが優れています。

CTEが選択したクエリでのみテンポラリテーブルを作成するとは思えませんが、3回は大きなテーブルを選択します。

関連する問題