2011-01-20 6 views
3

SQL Server 2005には、クラスタ化されていないキーを使用してレコードを選択する必要がある大きなテーブルがあり、できるだけこのプロセスを最適化しようとしています。一貫性のないSQL Server実行計画のキー参照

テーブルにはかなりの数の列があり、3つの異なる列に非クラスター化インデックスを追加しました。

SELECT * FROM table WHERE Field1 = 10; 
SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field3 = 'A'; 

Field1とField2は整数フィールド、Field3はvarcharです。

SELECT -> Nested Loop -> Index Seek 
         -> Key Lookup 

しかし、私はその実行時間が大幅に矛盾していることを見つける:私はこれらの3件の問い合わせのためのSQL Serverからの推定クエリ実行プランを要求すると

は、私はそれぞれのために基本的に同じプランを取得します。具体的には、2番目のクエリはクエリの合計コストの98%を占めます。 Key LookupのステップがIndex Seekと比較して100%のコストを有することを除いて、その実行計画は他のものと同じです。他の2つのクエリでは、50%に近くなります。

Key Lookupは望ましくないことを理解しており、余分な列を参照する必要がないように列にインデックスを追加することで回避できます。しかし、この場合、テーブル内のすべての列が返されるようにして、それらをすべてインデックスに追加するのは意味がありません。しかし、どのようにして1つの索引でKey Lookup操作に別のKey Lookupよりも時間がかかるのですか?

答えて

1

しかし、どのように一つのインデックスは、別のキー参照よりもそんなに長く を取るためにキー ルックアップ操作を引き起こす可能性が?

これはすべて、予想される鍵長の現在の統計情報に依存します。

クエリオプティマイザ(QO)は、インデックスの統計情報を調べることによって機能します。フィールドbのインデックスは平均カーディナリティ100を持つことができますが、他のフィールドのインデックスは平均カーディナリティ10000(100倍特殊)です。したがって、それはaveraged計画に基づいて相対的な表示を与えます。

詳細を表示するには、常に統計情報*をオンにします。実際には、特定の値のactual execution timeしか表示されません。いくつかの点で、アクセス変数がランダムであれば、QOは長期にわたってより正確になります。

は、これらの2つのクエリ

SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field2 = 42; 

の場合は、のは、仮に42は、すべてのレコードの80%で使用される特殊なコードであるとしましょう考えてみましょう。 40は1レコードのみで使用されるユニークなコードです。 QOにはそれぞれ異なる見積もり行が表示されるとは思いませんか?しかし、クエリを実行した場合、パラメータ化/プランキャッシングが関与していない場合、80%(高価な)ブックマーク検索を実行する代わりにclustered indexを使用してテーブルをスキャンする可能性があります。

set statistics io on 
set statistics time on 
を報告し、統計をオンにする

*

0

「クエリのコスト(バッチに相対)」のパーセンテージが、最小限に抑えるために誤解を招く可能性がある場合があります。

実際の実行計画をioと時間の統計と併せて調べると、実際に何が起こっているのかを理解する方がよいでしょう。

set statistics io on 
set statistics time on 

SELECT * FROM table WHERE Field1 = 10; 
SELECT * FROM table WHERE Field2 = 40; 
SELECT * FROM table WHERE Field3 = 'A'; 

次に、各クエリで返される論理読み取り、CPU時間、および経過時間を確認します。

2

コストは必ずしも時間に関係するものではなく、代わりにリソース消費に関連しています。実際に何が起きているのかは、クエリを見たり、テーブル構造を知ったり、カラムに含まれているデータの構成を見たりすることなしには言い難いです。しかし、条件に合致するレコードの数は、異なるクエリプランのコストを変えることができます。

テーブルのインデックスについては、できるだけ多くの条件列をインデックスに含めることができます。データに応じて、最も選択度の高い列(最も多くのデータを排除する可能性が高い列)に索引付けすることで、より良い効果を得ることができます。ただし、必ずしもそうである必要はありません。特に、他のテーブルと結合して結果を並べ替える場合など、必要に応じて他の列を追加することができます。索引を作成するときに「include」句を使用して、選択肢の少ない「where」列を索引に追加して、必要なキー参照の数を減らすことができます。

関連する問題