web-dev-qa-db-ja.com

一時テーブルとサブセレクトのパフォーマンスに大きな違いがあるのはなぜですか

これは、SQL Server 2008 R2に関する質問です

私はDBAではありません。私はJava開発者であり、時々SQLを作成する必要があります。主にコードに埋め込まれています。)ここで何か間違ったことをしたかどうか、そしてそうであれば、私は二度と起こらないようにすることができます。

Q1:

SELECT something FROM (SELECT * FROM T1 WHERE condition1) JOIN ...

Q1には14の結合があります

Q2はQ1と同じですが、1つ例外があります。 (SELECT * FROM T1 WHERE condition1)は、前に実行され、一時テーブルに保存されます。

これは相関サブクエリではありません。

Q2:

SELECT * INTO #tempTable FROM T1 WHERE condition1
SELECT something FROM #tempTable  JOIN ...

再び、14が参加します。

今私を困惑させているのは、Q1(2回のクエリを組み合わせて)が2秒かかったのに対し、Q1は2分以上かかった(キャッシングを避けるために数回試してみた)ことです!!!何が得られますか?

36
Ward

なぜサブクエリの使用が推奨されないのですか?

データベースオプティマイザー(使用しているデータベースに関係なく)は、そのようなクエリ(サブクエリ)を常に適切に最適化できるとは限りません。この場合、オプティマイザーの問題は、結果セットを結合する正しい方法を選択することです。 2つの結果セットを結合するためのアルゴリズムがいくつかあります。アルゴリズムの選択は、一方と他方の結果セットに含まれるレコードの数に依存します。 2つの物理テーブルを結合する場合(サブクエリは物理テーブルではありません)、データベースは利用可能な統計によって2つの結果セットのデータ量を簡単に判断できます。結果セットの1つがサブクエリである場合、それが返すレコードの数を理解することは非常に困難です。この場合、データベースは誤った結合のクエリプランを選択する可能性があるため、クエリのパフォーマンスが劇的に低下します。

一時テーブルを使用してクエリを書き換えることは、データベースオプティマイザーを簡素化することを目的としています。書き換えられたクエリでは、結合に参加するすべての結果セットは物理テーブルになり、データベースは各結果セットの長さを簡単に決定します。これにより、データベースは、可能なすべてのクエリプランの中で保証された最速を選択できます。さらに、データベースは、どのような条件であっても正しい選択を行います。一時テーブルを使用して書き換えられたクエリは、どのデータベースでもうまく機能します。これは、ポータブルソリューションの開発において特に重要です。さらに、書き換えられたクエリは読みやすく、理解しやすく、デバッグしやすいです。

一時テーブルを使用してクエリを書き換えると、追加の費用(一時テーブルの作成)のために速度が低下する可能性があることが理解されています。データベースがクエリプランの選択と間違えない場合、新しいクエリよりも古いクエリをより速く実行します。ただし、この速度低下は常に無視できます。通常、一時テーブルの作成には数ミリ秒かかります。つまり、遅延はシステムパフォーマンスに大きな影響を与えることはできず、通常は無視できます。

重要!一時テーブルのインデックスを作成することを忘れないでください。インデックスフィールドには、結合条件で使用されるすべてのフィールドを含める必要があります。

48
Karthik AMR

ここで取り組まなければならないことがたくさんあります。インデックス、実行計画などです。結果をテストして比較するのが方法です。

通常の容疑者であるインデックスを調べることができます。実行計画を調べて比較します。 WHERE句が正しいものを使用していることを確認してください。 JOINsでインデックスを使用していることを確認してください。

これらの答えはきっとあなたに大いに役立つでしょう。

9
Yaroslav