1つまたは2つのインデックス?


11

データベースのテーブルに次のインデックスを作成しました。

CREATE INDEX [idx_index1]
on [table1]
(col1, col2, col3)

サーバーは次の「不足している」インデックスを提案しています:

CREATE INDEX [idx_index2]
on [table1]
(col1, col2)
INCLUDE (col3, col4, col5, col6....)

維持する必要のある新しいインデックスを作成するのではなく、提案された列を含めるように既存のインデックス定義を修正するのは私には理にかなっています。col1とcol2を選択するクエリは、index1をindex2と同じくらい効果的に使用できます。私は正しいのですか、それとも何か不足しているのでしょうか?

回答:


12

そして、パフォーマンスチューニングとインデックス作成戦略の芸術に入ります...

提案された列を含めるように既存のインデックス定義を修正するのは私には理にかなっているようです

私はあなたの見積もりを取り、3番目のインデックス定義を記述します。

create index [idx_index3]
on [table1] (col1, col2, col3)
include (col4, col5, col6....);

それはCREATE INDEXあなたの引用文に対応する文でなければなりません。

それはまさしく賢明な解決策かもしれませんが、それは依存します。状況に応じていくつかの例を示します。

次のようなクエリで主に構成される一般的なワークロードがある場合:

select col1, col2, col3
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

その後、あなたのidx_index1インデックスはしっかりしているでしょう。完全に狭く、無関係なデータが含まれていない(クラスター化インデックスの定義があったとしても考慮されない)クエリを満足するインデックスです。

しかし、主に次のようなクエリで構成されるワークロードがある場合:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2;

それidx_index2は、クラスター化インデックスへのキールックアップ(またはヒープへのRIDルックアップ)の必要性を防ぐカバリングインデックスと呼ばれるものであるため、賢明です。その非クラスター化インデックスの定義は、クエリが必要とするすべてのデータを網羅するだけです。

あなたの推薦があれば、それは次のようなクエリに適しています:

select co11, col2, col3, col4, col5
from table1
where col1 = 1
and col2 = 2
and col3 = 3;

あなたのidx_index3勧告はカバー指標になり満足していることを上記のクエリの検索条件。

私が理解しようとしている点は、このような孤立した質問にあります。これには明確に答えることはできません。それはすべて、一般的で頻繁なワークロードが何であるかに依存します。もちろん、常に3つのインデックスすべてを定義して各サンプルクエリタイプを処理できますが、これらのインデックスを更新し続けるために必要なメンテナンスが問題になります(INSERT、UPDATE、DELETEなど)。これがインデックスのオーバーヘッドです。

ワークロードを分析して評価し、利点が最も効果的な場所を決定する必要があります。最初のサンプルクエリが1秒あたり数十回も実行されることが最も一般的で、3番目のサンプルクエリのように非常にまれなクエリがある場合、インデックスのリーフレベルページを膨らませても意味がありませんINCLUDE非キー列。それはすべてワークロードに依存します。

賢明なインデックス作成戦略を理解し、一般的なワークロードを理解している場合は、それらの両方を適用することで、最適なルートを見つけることができます。


私はしばらくそれを消化しなければならないつもりですが、それは良い答えのようです。あなたが定義した 'index3'には、等値列であるcol3と含まれている列があるというタイプミスだったと思いますか?
ポール2013年

うん:-)良いキャッチ。私はそれを編集しました。
Thomas Stringer 2013年

言うまでもなく、テーブルに列1〜6しかない場合は、インデックス1および2と3〜5を含めるのはばかげています。
ケネスフィッシャー

1
@KennethFisher-なぜそれがばかげているのでしょうか?データベースの構造とワークロードがそれを保証する場合、それは十分に妥当なことのようです。たとえば、列1と2の値に基づいて列1〜5を選択するクエリがあり、おそらく列6がインデックスを膨らませたくないnvarchar(max)列であるとします。
ポール2013年

1
@paulHこれはおそらく私の意見ですが、インデックスにテーブル内の列の90 +%が含まれるように十分な数の列を追加した時点で、テーブルに移動するための追加の読み取りまで、インデックスを膨らませています。それ自体はそれほど重要ではありません。今、確かに例外があります.. cols 1-5がすべてintで、col6がvarchar(max)の場合、私はそれを行うかもしれません。しかし、一般的に私はそれらを非常に注意深く見ます。
ケネスフィッシャー

7

あなたは確かに正しいので、DBA が欠落しているインデックスDMVなどによって提示された「提案」を常に確認することが重要である理由を発見しました。

不足しているインデックスDMVによって提供される提案が単独で提示されることを考慮してください。つまり、SQL Serverは、他にどのようなインデックス構造が既に存在しているかに関係なく、推奨構造のインデックスがクエリに役立つと判断しました。


3

もう少し、トーマスの答えの含意の1つについて:

彼は言った:

もちろん、常に3つのインデックスすべてを定義して各サンプルクエリタイプを処理できますが、これらのインデックスを更新し続けるために必要なメンテナンスが問題になります(INSERT、UPDATE、DELETEなど)。これがインデックスのオーバーヘッドです。

したがって、別の大きな問題が発生します。テーブルはどのくらいの頻度で更新されますか?

最初に、常に更新されるテーブルの例を考えてみましょう。たとえば、ORDERSWebサイトの消費者の活動を反映する小売テーブルなどです。複数のインデックスを作成することに注意を払う必要があります。これは、インデックスが常に更新されるため、作業が増えるためです。常にデータベースのパフォーマンスに影響します。

一方、ウェブサイトの設定の一部としてのみ更新されるテーブルを考えてください。ほとんどの値に対して一度更新され、値はほとんど追加されません。そこで、更新速度の低下はほとんど考慮されません。複数のインデックスは、データベースインデックスの再構築と再編成を遅くする可能性がありますが、それらが十分に高速である限り、自由に感じてください。複数のインデックスが読み取りを高速化する場合は、それを試してください。

真ん中のケースは、通常はバッチプロセスで一晩のみ更新されるテーブルです。そこでは、複数のインデックスからの更新速度の低下は、日中のパフォーマンスには影響しません -それらは、(1)夜間バッチメンテナンスを実行するのにかかる時間、(2)同時プロセスのパフォーマンス、および(3)にかかる時間にのみ影響しますインデックスの再編成などのデータベース保守タスク。したがって、これら3つのアリーナのプロセスが十分に高速に実行されている限り...クエリを高速化するインデックスを作成します。

HTH ...

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.