データ件数が膨大で、一方に絞り込んだデータ郡に対する検索の頻度が利用方法の大多数を占めるなら効果はあると思います。
sql
1SELECT *
2FROM item
3WHERE st = 2 /* 未販売 */
4AND price > 1000
このようなSQL発行が多く、未販売が100件程度で販売済みが数百万件のような場合、st(未販売or販売済み)にindexがあればSQLの実行自体は高速化されるでしょう。
「未販売」と「販売済み」を選り分ける作業がindexによってほぼ無くなる程度まで軽減されるので、この作業のコストが高ければ高いほど(つまりレコード件数が多いほど)効果があります。
そして(上記の設定のように)その選り分ける作業こそがそのSQLのコストの大半だったなら、高速化率も高くなります。
しかしこのような場合は、まず販売済みの古いデータを定期的にバックアップに移して省くことを検討したほうが良いかもしれません。あまりにレコードが多いとデータ登録時のindex作成も負担になってくるためです。(データ件数が膨大ということは登録や更新も頻繁に行われるということですし)
追記
ところで上記のような例でpriceにもindexがあり、全体に対する「price > 1000」が「st = 2」よりも少ないと簡単に予測できる場合、オプティマイザは「price > 1000」を先に実行するプランを選択するかも知れません。そうすると「st = 2」のために極少数のレコードのソートで済みstへのindexにあるなしに関わらず実行速度が殆ど変わらなかった。ということもあるかも知れません。
以下の部分はコメントで指摘いただいた通り誤りで、極端に分布が偏った方を参照するのでない限りindexに意味は無いようです。
カーディナリティが低くても、対象テーブルのレコードの分布に偏りがある場合は
仮に偏りが無くても、また100:100万に対して100万の方を選択する絞込みだったとしても、ソートが必要になる時点でindexには意味が出てくるように思います。
そして絞込みや検索には大抵ソートが必要です。(たぶん)
カーディナリティが高い例えばユニークidのような要素だと、indexはその要素を条件にした結合などの操作にも威力を発揮します。しかしカーディナリティが低い要素では境界を発見するような操作にしか威力を発揮できないので、コストが同じな割りに用途が少なく効率が悪いということだと思います。
でも”その操作をこそメインに頻繁に行う”のであれば意味はあるんじゃないかな。。
2016/08/05 01:03
2016/08/05 09:04
2016/08/05 09:05
2016/08/05 09:25
2016/08/05 09:56 編集
2016/08/05 10:07