クエリのタイプごとに個別のインデックスが必要ですか、それとも1つのマルチコラムインデックスが機能しますか?
-
16-10-2019 - |
質問
私はすでにこの質問に対する答えを幾分知っていますが、私はいつも、このトピックを取り上げる必要があることがもっとあると感じています。
私の基本的な理解では、一般的に言えば、あなたが照会/並べ替えがいつでも有用ではない可能性があるすべてのフィールドを含む単一のインデックスは、このタイプのことを見たことがあるということです。ように、誰かが「まあ、これらすべてのものをインデックスに配置するだけで、データベースはそれを使用して必要なものを見つけることができます」と考えました。
そうするテーブルを想像してみてください:
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
このようなクエリの場合、より良いアイデアは、 customerId
と dateCreated
フィールド、 customerId
フィールドは「最初」です。これにより、このクエリが必要なものを迅速に見つけることができるようにデータを編成するインデックスが作成されます。
おそらく最初と同じくらい頻繁に見られるもう1つのことは、各フィールドの個々のインデックスです。だから、それぞれ1つ name
, customerId
と dateCreated
田畑。
最初の例とは異なり、このタイプの配置は、少なくとも部分的に有用であることがあるように思えます。クエリの実行計画は、少なくともそれがでインデックスを使用していることを示している場合があります customerId
レコードを選択するには、インデックスを使用していません dateCreated
それらをソートするフィールド。
これは幅広い質問であることを知っています。なぜなら、特定のテーブルの特定のクエリに対する特定の回答は、通常、実行計画がそれがやろうとしていることを確認することであり、そうでなければテーブルの詳細とクエリの詳細を取ることであるためアカウント。また、特定のインデックスを維持するオーバーヘッドとは対照的に、クエリが実行される頻度に依存することを知っています。
しかし、私が尋ねているのは、インデックスの一般的な「出発点」として、特定の頻繁にプルされたクエリと条項または順序のフィールドの特定のインデックスを持っているという考えは理にかなっていると思いますか?
解決
あなたの例のクエリがそのインデックスを使用しないという点であなたは正しいです。
クエリプランナーは、次の場合のインデックスの使用を検討します。
- その中に含まれるすべてのフィールドは、クエリで参照されます
- 最初から始まるフィールドのいくつかは参照されます
クエリでは使用されていないフィールドから始まるインデックスを使用することはできません。
だからあなたの例については:
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]
たとえば、インデックスとして、クエリプランナーは、それをJustのインデックスを使用するクエリに使用できることを忘れないでください [customerId]
存在する場合。ただ使用している間 [customerId]
複合インデックスを使用するよりもわずかに効率的です。これは、1つではなくRAMのスペースを競う2つのインデックスを持つことになる可能性があります(ただし、通常の作業セット全体がRAMに簡単に適合する場合、この余分なメモリ競争は問題ではないかもしれません) 。
他のヒント
元の質問に答えるには、はい、インデックスを中心に設計する必要があります クエリ, 、ただだけではありません テーブル. 。インデックス内のフィールドの順序は非常に重要です。複数のクエリに最適になるように単一のインデックスを設計することはより困難であり、トレードオフを行う必要があります。
あなたの2番目のポイントに関しては、はい、単一の個々のフィールドに関する多くのインデックスが迷惑に一般的です。私は自分の環境で常にそれを見ていますが、通常、開発チームが適切なインデックスを設計するためにDBAと協力していないことを私にとっては私にとっては私にとっては私にとっては赤い旗です。
インデックスを設計するための私の戦略は、インデックスを作成することです。
- (選択性の順に)どこで使用されるフィールド
- 順番に使用されるフィールド
- カバーインデックスを作成するために(必要に応じて)他のフィールドを含める
だからあなたの例については:
SELECT [id], [name], [customerId], [dateCreated]
FROM Representatives WHERE customerId=1
ORDER BY dateCreated
おそらく(customerID、dateCreated)にインデックスを設計するでしょう(id、name)。このカバーインデックスにより、クエリが元のテーブルを押す必要がなく、パフォーマンスが大幅に向上することを意味します。
この例はほとんどです それも ただし、シンプルです。 Just(CustomerID)の素朴なインデックスもほぼ同様に機能します(各顧客には1人の担当者しかないと仮定すると、テーブルの1つのブックマーク検索のみが必要になります)。また、実際に行うことは有益かもしれません クラスター化 他のクエリがテーブルに対して実行されるものに応じて、(CustomerID、ID)のインデックス。