以下はいつ必要になりますか。
create index i_t_a_b on t(a,b);
create index i_t_b_a on t(b,a);
以下はいつ必要になりますか。
create index i_t_a_b on t(a,b);
create index i_t_b_a on t(b,a);
最大の検索速度が必要で、結合条件または where 条件に両方の列がある場合、ただし、列 a の選択性が高く、列 b の選択性が高い場合があり、単一のインデックスからその事実を利用したい場合があります。
また、マシンのデータサイズ/パフォーマンスの比率は非常に高いはずであり、同時に(推測して)何らかの改善が必要であると(たとえ数パーセントであっても)喜んで呼ぶ必要があると思います.
それでも、経験は、物事が多くの要因に依存することを教えています。特定の RDBMS およびアプリケーション環境では、独自のベンチマークをより適切に実行できます。
編集: 複合インデックスに関する詳細な説明。ウィキペディアから:
「インデックス定義で列がリストされている順序は重要です。最初のインデックス付き列のみを使用して行識別子のセットを取得することは可能です。ただし、(ほとんどのデータベースでは) 取得することは不可能または効率的ではありません。 2 番目以降のインデックス付き列のみを使用する行識別子のセット.
たとえば、最初に市区町村、次に姓、名の順に編成されている電話帳を想像してください.市区町村が指定されている場合、簡単に抽出できますその都市のすべての電話番号のリスト. ただし、この電話帳では、特定の姓のすべての電話番号を見つけるのは非常に面倒です. 各都市のセクション内でその姓のエントリを探す必要があります. "
ウィキペディアの説明は単純化しすぎているかもしれませんが、基本的な考え方は理解できます (類推すると、電話帳には通常クラスター化されたインデックスがあり、それは一般的なデータベース インデックスではないことに注意してください)。
インデックスのサイズ、データ構造のサイズ、使用可能なメモリ、インデックスの最初の列の選択性によっては、テーブル スキャンを使用するよりも、間違った順序で並べられたインデックスを使用する方がはるかにコストがかからない場合があります。
ああ、あなたが探している例とのより良い類似性を考えてみてください素敵な教科書を想像してみてください。それには、章と節とそれらが位置するページの数を含む目次があります(これはポインタを保持する非クラスター化インデックスです)データレコード - ページ)。ここで、教科書が SQL-92 標準に基づいていると想像してください。TOC のほとんどの用語は SQL 用語になります (この仮定は保持されます)。また、本の最後に別の索引を付けて、すべての興味深い用語をアルファベット順にリストし (主要な章の名前と仮定しましょう)、ページ番号を付けます。
「DISTINCT が表示されるすべての章を教えてください」などの質問には、2 番目のインデックスを使用します。(後の分野の選択性が高いため)
「最初の章に表示される用語の数を教えてください」などの質問には、TOC を使用します。
「SELECT は DML の章で説明されていますか?」などの質問に対して、どちらのインデックスも使用できます。(両方のフィールドの選択性が高いため)ただし、DML 自体の TOC が 3 ページの長さで、インデックスの SELECT エントリが 15 行しかない場合は、おそらく 2 番目のエントリに移動します。これは、両方の利点を享受する場合の例ですインデックス。
さて、それが行き過ぎだと思われる場合は、スキャンされた議会図書館のデータベースを考慮してください. :)
前に述べたように、すべての計画は問題ありませんが、最後に独自のベンチマークを実行してください。
あなたがそれを必要とする実際のケースはないと思います。
テーブルにさらに多くの列があり、一意ではなく、次の両方のクエリで高いパフォーマンスが必要な場合に、これは理にかなっていa
ますb
。
Select Max(b) From t Where a=1 --# Would use i_t_a_b
と
Select Max(a) From t Where b=1 --# Would use i_t_b_a
テーブルが次のようになっているとします。
a b c d e
- - - - -
0 8 x x x
0 9 x x x
1 8 x x x
1 9 x x x
i_t_a_b
次のようになります。
0
8
9
1
8
9
i_t_b_a
次のようになります。
8
0
1
9
0
1
Select Max(b) From t Where a=1
ですべての行を見つけるには8
、 とを掘り下げる必要があります。これは、テーブル全体のスキャン (すべてを読み取る必要がある) よりもはるかに高速ですが、を使用するほど高速ではありません。9
i_t_b_a
a=1
x
i_t_a_b