DBA として長年の経験を積んできた私は、この質問に対する答えを知っていると確信しています。
SQL Server を使用して、 columnAおよび columnにインデックスがあり、column 、、Bおよび に 2 番目のインデックスがあるテーブルがあると仮定すると、最初のインデックスを削除しても安全です。最初のインデックス?ABC
DBA として長年の経験を積んできた私は、この質問に対する答えを知っていると確信しています。
SQL Server を使用して、 columnAおよび columnにインデックスがあり、column 、、Bおよび に 2 番目のインデックスがあるテーブルがあると仮定すると、最初のインデックスを削除しても安全です。最初のインデックス?ABC
状況によって異なりますが、答えは「はい、(A、B)にインデックスをドロップできます」であることがよくあります。
カウンターケース((A、B)のインデックスを削除しない場合)は、(A、B)のインデックスが制約を適用している一意のインデックスである場合です。次に、(A、B)にインデックスをドロップしたくありません。(A、B、C)のインデックスも一意である可能性がありますが、(A、B)の組み合わせは他のインデックスのために一意であるため、一意性は冗長です。
ただし、このような異常なケースがない場合(たとえば、(A、B)と(A、B、C)の両方で重複エントリが許可される場合)、(A、B)インデックスは論理的に冗長です。ただし、列Cが「ワイド」(おそらくCHAR(100)列)で、AとBが小さい(たとえばINTEGER)場合、(A、B)インデックスは(A、B、C)よりも効率的です。 )(A、B)インデックスのページごとに、より多くの情報を読み取ることができるため、インデックス。したがって、(A、B)は冗長ですが、保持する価値がある場合があります。テーブルのボラティリティも考慮する必要があります。テーブルがめったに変更されない場合、追加のインデックスはそれほど重要ではありません。テーブルが大幅に変更される場合、追加のインデックスはテーブルへの変更を遅くします。それが重要かどうかを推測するのは難しいです。おそらくパフォーマンス測定を行う必要があります。
最初のインデックスは を検索するクエリをカバーしA、 2 番目のインデックスは を検索するクエリ、または明らかに最初のケースのスーパーセットであるA,Bクエリをカバーするために使用できます。AA,BA,B,C
が非常に広い場合でも、より少ない読み取りで特定のクエリを満たすことができるためC、インデックス onA,Bは依然として有用な場合があります。
たとえばC、char(800)列の場合、次のクエリは、より狭いインデックスを使用できるようにすることで大きなメリットが得られる可能性があります。
SELECT a,b
FROM YourTable
ORDER BY a,b
はい、これは一般的な最適化です。A、B のインデックスから恩恵を受けるクエリは、A、B、C のインデックスからも同様に恩恵を受けることができます。
MySQL コミュニティには、スキーマ全体で冗長なインデックスを検索するツールもあります: http://www.percona.com/doc/percona-toolkit/pt-duplicate-key-checker.html
考えられる例外ケースは、A、B のインデックスがよりコンパクトで、より頻繁に使用され、どのインデックスをメモリにロードしたままにするかを制御したい場合です。
私が考えていたことの多くは、以前の回答でジョナサンによって書かれました。ユニークさ、仕事の速さ、そして彼が見逃していたと私が思うもう 1 つのこと。
最初のインデックスが作成されA desc, B asc、2番目の場合、最初のインデックスA asc, B asc, C ascを削除することは実際には方法ではありません.2番目のインデックスは最初のインデックスのスーパーセットではなく、順序が最初に書いたもの。
最初のインデックスを使用する場合など、場合によってはorder by A desc, B asc(もちろん) とA asc, B descを実行できますが、 のように、そのインデックスの任意の部分を使用するクエリを作成することもできますOrder by A desc。
ただし、 のようなクエリはorder by A asc, B asc、最初のインデックスによって「カバー」されません。
つまり、通常は最初のインデックスを削除できますが、それはテーブルの構成とクエリ (そしてもちろんインデックス) によって異なります。
私は通常、履歴データを含むテーブルでこの「ほぼ」類似したインデックスを見つけます。が日付または整数列の場合column Cは、注意してください。WHERE tblA.C = MAX(tblB.C)これは、テーブルを完全にスキップし、インデックスのみのアクセスパスを利用するのように、MAX関数を満たすために使用される可能性があります。