0

クエリ 1) == 2) は、推定クエリ プランと実際のプランのどちらですか? (統計はここで実際の計画に影響を与えることができますか?)

declare @cat int -- prc からの入力パラメータ

...

1)

select * 
from A as a
  join B as b
    on b.id = a.id
    on b.cat = @cat
  join C as c
    on c.fid = b.fid
    on c.cat = @cat
  where a.cat = @cat

2)

select * 
from A as a
  join B as b
    on b.id = a.id
    on b.cat = a.cat
  join C as c
    on c.fid = b.fid
    on c.cat = b.cat
  where a.cat = @cat

これらは論理的に同等であるべきであり、テーブルの実際の違いに関係なく、実行計画は常に同じであるべきだと私には思えます。また、結合、または場所に条件を追加したり、結合するテーブルを追加したりしても、これは変わりません。

これが正しくない場合はありますか?

4

1 に答える 1

0

オプティマイザーは、a.cat、b.cat、または c.cat のいずれかに使用可能なインデックスがあるかどうか、およびそのインデックスに関連する id または fid 列も含まれているかどうかによって影響を受ける可能性があります。単純な WHERE 句の述語をテーブル レベルの操作にプッシュするのは賢明かもしれません。また、テーブルの統計の影響を受ける場合もあります。(パラメーターの値がたまたま C に 1 回だけ出現する場合、A の処理を​​開始するよりも C の処理を​​開始する方がはるかに効率的である可能性があります。または、B から開始する方が効率的である可能性があります。 A から始めます。また、ステートメントが準備されたときにそれを見ることができるのではなく、ステートメントが実行されるまでオプティマイザーがパラメーターの値を知らないことは問題になる場合とそうでない場合があります。)

したがって、コメントですでに暗示されているように、スキーマなどを含め、使用しているシステムについて詳しく知らずに作成できる決定的なステートメントはありません。

幸いなことに、結果の内容は同じである必要があります。実行計画についての保証はありません。


ほとんどの SQL システムでは、結合ごとに 1 つのキーワード ON が必要であることに注意してください。

select * 
from A as a
  join B as b
    on b.id = a.id
    AND b.cat = @cat
  join C as c
    on c.fid = b.fid
    AND c.cat = @cat
  where a.cat = @cat

Xerion は次のように尋ねました。

実行計画が異なる可能性があることを考えると、どの方法のクエリが「優れている」か。ベターは次のように定義されます。

  1. より良い計画を提供するために最適化される可能性が高くなります (または SQL オプティマイザーを混乱させる可能性が低くなります)。
  2. SQL 規則との一貫性が向上しました。

DBMS とそのオプティマイザーに多少依存します。この分野では経験論に代わるものはありませんが、ある時点で経験的に決定されたことが、別の時点では誤りである可能性があることを忘れないでください。

  1. データセットのサイズが変更されました
  2. データセットの統計分布が異なるようになりました
  3. オプティマイザが変更された可能性があります
  4. 利用可能な異なるインデックスがある場合があります

結合を行うには多くの方法があり、(それでも) 使用可能なインデックスに依存します。私はおそらく次のように書くでしょう:

SELECT * 
  FROM A JOIN B ON b.id  = a.id  AND b.cat = a.cat
         JOIN C ON c.fid = b.fid AND c.cat = b.cat
 WHERE a.cat = @cat
   AND b.cat = @cat
   AND c.cat = @cat

ここでの論理は、A(id, cat) と B(id, cat)、および B(fid, cat) と C(fid, cat) にインデックスが存在する可能性が高いため、オプティマイザは完全に活用できるということです。それらのインデックス。WHERE 句には 2 つの冗長な用語が含まれていますが、オプティマイザに何が必要かを知らせ、他の方法では推定できないことを明示的に伝えます。オプティマイザーの品質に自信がある場合 (およびオプティマイザーが生成するクエリ プランを確認している場合) は、WHERE 句の 3 つの条件のうち 2 つを削除できます。

パラメータを ON 句に配置すると、オプティマイザはそれがないとインデックスを十分に活用できない可能性があります。オプティマイザがどのように動作するかを調べるために実験する必要があります。

最後に、既に述べたように、テーブルの一連のインデックスは非常に重要であり、DBMS が必要とするすべての統計が最新であることを確認することが重要な場合がよくあります。また、テーブルが最初は小さい場合、オプティマイザーはテーブルが大きくなったときとは異なるクエリ プランを選択する可能性があることに注意してください。そのため、適切なレベルでテストを行ってください。運用テーブルに数十行しか含まれない場合を除き、数十行しかないテーブルでクエリのパフォーマンス テストを行わないでください。

于 2010-01-15T16:44:36.893 に答える