1

クラスタ化インデックスによってテーブル内のレコードをルックアップするために使用されるビューがあります。このビューには、selectステートメントに2つのサブクエリがあり、クラスター化インデックスによって2つの大きなテーブルのデータをルックアップします。

非常に単純化すると、次のようになります。

SELECT a,
(SELECT b FROM tableB where tableB.a=tableA.a) as b
(SELECT c FROM tableC where tableC.a=tableA.a) as c
FROM tableA

[tableB]へのほとんどのルックアップは、[tableB]の非クラスター化インデックスを正しく使用し、非常に効率的に機能します。ただし、SQL Serverが実行プランを生成する際に、渡される値を含まない[tableB]のインデックスを使用することが非常にまれです。したがって、上記の例に従って、列[a]のインデックスはtableBに存在しますが、プランは代わりに列[z]を持つクラスター化インデックスのスキャンを実行します。SQL独自の言語を使用すると、プランの「述語はオブジェクトに関連しません」。なぜこれが実用的であるのかわかりません。その結果、SQLがこれを行う場合、インデックス内のすべてのレコードをスキャンする必要があります。これは、SQLが存在しないため、最大30秒かかるためです。いつも、それは明らかに間違っているようです。

実行計画が決して正しくないように見える何かをするところで、これを以前に見た人はいますか?とにかくクエリを書き直すつもりなので、私の懸念はクエリの構造ではなく、SQLがなぜそれを間違ってしまうのかということです。

SQL Serverは、一度機能したプランを選択でき、データセットが変更されると非効率になることがありますが、この場合は機能しません。

さらに詳しい情報

  • [tableB]には400万件のレコードがあり、[a]のほとんどの値はnullです。
  • プランを生成した最初のクエリを取得できません
  • これらのクエリはColdfusionを介して実行されますが、現時点では、SQLServerでこれを個別に見た人に興味があります。
4

1 に答える 1

3

いつも、それは明らかに間違っているように思えます。

First Rule of Programmingに興味があるかもしれません。

したがって、上記の例に従って、列 [a] のインデックスが tableB に存在しますが、プランは代わりに列 [z] を持つクラスター化インデックスのスキャンを実行します。

クラスター化インデックスには常にすべての行が含まれます。順になっている可能性がありzますが、リーフ レベルには他のすべての列が含まれます。

SQL Server がインデックス シークよりもクラスタ化されたスキャンを好む場合がある理由はこれです。インデックス シークを行うときは、インデックスにない列を取得するために、クラスター化インデックスへのブックマーク ルックアップを実行する必要があります。

クラスター化インデックス スキャンを実行すると、定義上、すべての列が検出されます。つまり、ブックマークの検索は必要ありません。

SQL Server が多くの行を予期している場合、ブックマーク ルックアップを回避しようとします。これは長年の選択です。非クラスター化インデックス シークは、クラスター化インデックス スキャンによって定期的に打ち負かされます。

with (index(IX_YourIndex))クエリ ヒントでいずれかを強制することにより、ケースでこれをテストできます。

于 2013-01-11T12:12:44.860 に答える