クエリの種類ごとに個別のインデックスが必要ですか、それとも1つのマルチカラムインデックスが機能しますか?


22

私はこの質問に対する答えをすでにある程度知っていますが、私は常にトピックについて取り上げる必要があると感じています。

私の基本的な理解は、一般的に言って、特定の時点でクエリ/ソートを行う可能性のあるすべてのフィールドを含む単一のインデックスは有用ではない可能性が高いということです。誰かが考えたように、「まあ、すべてのものをインデックスに入れると、データベースはそれを使って必要なものを見つけることができます」、実際に実行されているクエリの実行計画を見たことがありません。

次のようなテーブルを想像してください。

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

およびフィールドを含む単一のインデックスが表示されるname場合がcustomerIdありdateCreatedます。

しかし、私の理解では、そのようなインデックスは、たとえば次のようなクエリでは使用されません。

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

このようなクエリの場合、より良いアイデアは、フィールドが「最初」であるフィールドcustomerIddateCreatedフィールドを含むインデックスになると思われますcustomerId。これにより、このクエリが必要なものを必要な順序ですばやく見つけることができるようにデータが編成されたインデックスが作成されます。

私が見るもう1つのことは、おそらく最初と同じくらい頻繁に、各フィールドの個々のインデックスです。そう、1それぞれにnamecustomerIdそしてdateCreatedフィールド。

最初の例とは異なり、このタイプの配置は、少なくとも部分的には役立つように思えます。クエリの実行プランは、少なくとものインデックスを使用customerIdしてレコードを選択しているが、dateCreatedフィールドのインデックスを使用してレコードをソートしていないことを示す場合があります。


テーブルの特定のセットに対する特定のクエリに対する具体的な答えは、通常、実行プランが実行することを示していることを確認することであり、そうでない場合はテーブルとクエリの詳細を取得することであるため、これは広範な質問であることを知っていますアカウント。また、クエリの特定のインデックスを維持するオーバーヘッドとは対照的に、クエリが実行される頻度に依存することも知っています。

しかし、私が求めているのはインデックスの一般的な「開始点」であり、頻繁にプルされる特定のクエリとWHERE句またはORDER BY句のフィールドに特定のインデックスを付けるという考えは意味がありますか?

回答:


27

サンプルクエリがそのインデックスを使用しないという点であなたは正しいです。

クエリプランナーは、次の場合にインデックスの使用を検討します。

  • クエリに含まれるすべてのフィールドが参照されます
  • 先頭から始まるフィールドの一部が参照されます

クエリで使用されていないフィールドで始まるインデックスを使用することはできません。

あなたの例では:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

次のようなインデックスを考慮します。

[customerId]
[customerId], [dateCreated]
[customerId], [dateCreated], [name]

だがしかし:

[name], [customerId], [dateCreated]

両方[customerId]を見つけ、どちら[customerId], [dateCreated], [name]か一方を優先するかどうかの判断が、フィールドのデータのバランスの推定値に依存するインデックスの統計に依存します。[customerId], [dateCreated]定義された場合、逆に特定のインデックスヒントを与えない限り、他の2つよりもそれを好むはずです。

私の経験では、フィールドごとに1つのインデックスが定義されていることも珍しくありませんが、挿入/更新でインデックスを更新するために追加の管理が必要であり、それらを格納するために必要な追加スペースが無駄になるため、これはめったに最適ではありませんそれらは決して使用されることはないかもしれませんが、DBが書き込み負荷の高い負荷を確認しない限り、パフォーマンスは過剰なインデックスでも悪臭を放ちません。

パフォーマンスの問題を別の問題と交換する可能性があるため、無理にしないでください。[customerId], [dateCreated]たとえば、インデックスとして定義する場合、クエリプランナーは[customerId]、存在する場合にのみインデックスを使用するクエリにそれを使用できることを忘れないでください。使用している間だけ[customerId]、この余分なメモリの競争がないかもしれませんあなたの全体の通常の作業セット収まる場合は簡単にRAMにかかわらず、これが(代わりに1のRAMにスペースを競合する2つのインデックスを持つ終わることによって軽減することができる化合物インデックスを使用して、よりわずかに効率的です問題)。


+1; 素晴らしい情報、特に、リマインダ(忘れがちです!)は、プランナクエリで最初のフィールドのみが必要なときに複合インデックスを使用できることを思い出させます。
アンドリューバーバー

6

元の質問に答えるために、はい、クエリを中心にインデックスを設計する必要がありますテーブルだけでなくあります。インデックス内のフィールドの順序は非常に重要です。単一のインデックスを複数のクエリに最適になるように設計するのは難しく、トレードオフを行う必要があります。

2番目の点については、はい、単一の個々のフィールドに多数のインデックスを作成するのは面倒です。私の環境では常に表示されますが、通常、開発チームが適切なインデックスを設計するためにDBAと協力していないことは危険です。

インデックスを設計するための私の戦略は、インデックスを作成することです。

  • WHEREで使用されるフィールド(選択性の順)
  • ORDER BYで使用されるフィールド
  • 必要に応じて他のフィールドを含めて、カバーするインデックスを作成します

あなたの例では:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

おそらく、(CustomerID、dateCreated)INCLUDE(id、name)のインデックスを設計します。このカバリングインデックスは、クエリが元のテーブルにヒットする必要がなく、パフォーマンスが大幅に向上することを意味します。

ただし、この例はほとんど単純すぎます。ちょうど(CustomerID)の単純なインデックスもほぼ同じように機能します(各顧客が1人の担当者しか持っていないので、テーブルへのブックマークのルックアップは1回だけであると仮定します)。また、テーブルに対して実行される他のクエリによっては、実際に(CustomerID、ID)でクラスター化インデックスを実行することも有益な場合があります。


「テーブルだけでなく、クエリを中心にインデックスを設計する必要があります」、および例が非常に単純であることに注意するなど、残りの答えに対する+1。
アンドリューバーバー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.