[WIP]SQLアンチパターン-12章 インデックスショットガン-まとめ
インデックスはただ貼れば良いということではない
結論としてはこうなります。
自分はインデックスについてきちんと分かっていなかったのですが、
調べてみるとインデックスって色々な種類があります。(インデックスで一般的によく使われているのが、B木インデックス
というものです。)
本も読んだりして、万能なインデックスなんて存在しないのだな、という認識に至りました。
DBの設計、取り出すデータの種類、アプリケーションレベルでのデータ扱いのロジック、実際に使用するクエリ構文によって有効なインデックスって変わるのだなと。
今回はそのインデックスについて、実際インデックスってなんなんですか?
それを少しでもわかりやすく書ければと思います。
(まだ十分に把握していない知識が多いので、今は必要な知識を全ては書けていません。それだけは分かっています。笑)
インデックスってそもそもなに?
このページが簡単に理解できるのかなと思います。
インデックスについて
ここも多分知っておくべき情報がいくつかあると思います。(筆者はまだ全部読みきっていませんのであとで読みます)
ある値を検索しようとなった時に、
その値がテーブルの何行目に格納されているのか、
それを示しているのがインデックスです。
そしてそのインデックスもまたテーブル構造で表されるので
DBにテーブルが1つ増えたような感じになるんですかね。
インデックスを貼りすぎるとどうなるのか
(自分、インデックスを貼る
という言い方がまだしっくりきていないです)
インデックスって要は1つのデータファイルです。
メモリ上に保存されることもあります。
(例えば使うかわからないけどとりあえず作っておこう!みたいなテンションで)インデックスファイルを作成しすぎるとどうなるでしょうか。
サーバー内の容量が圧迫されてしまうだけになります。SQL文を回す上でも余計なオーバーヘッドが出てきてしまうこともあります。
クエリとインデックスの正しい関係について
例えば、以下のようなテーブルがあったとしましょう
服(Clothes)テーブル
name | maker | created_at |
---|---|---|
タートルネック | アディダス | 2019-01-01 |
カーディガン | ユニクロ | 2018-01-01 |
Tシャツ | ナイキ | 2017-01-01 |
インデックスを作成する際は下記のようなコードになります。
CREATE INDEX MakerName ON Clothes(maker, name);
このインデックスはmaker
とname
が両方ある複合インデックスになります。
下記のように検索方法したらどうなるでしょうか
- 名前がタートルネック
の服を探したい
この場合、クエリはこうなります
SELECT * FROM Clothes WHERE 'name' = 'タートルネック';
このクエリを回す際に、先ほど作成した複合インデックスは使われません。
まずそもそも複合インデックスとはつまりどういうことか、認識を改める必要が自分にはありました。
複合インデックスはあくまで両方のデータを扱って検索した場合に使われます。
今回は検索するための条件としてname
しか使っていないので、インデックスは利用されません。
また、
SELECT * FROM Clothes WHERE 'name' = 'タートルネック' AND maker = 'アディダス';
としても、これも実はインデックスは利用されません。
なぜなら作成した複合インデックスは、最初にmaker
、次にname
という順番だからです。
複合インデックスでは定義の順番が実は重要ということになります。
インデックスが有効なケースを知ろう
まず、単純にインデックスを貼っただけではパフォーマンスが上がるということには繋がりません。
例えば、データの数が10個とか、そのくらいの数だとインデックスを作成したところで劇的にパフォーマンスが上がるということはありません。どのくらいの数からインデックスを作成することでパフォーマンスが上がるのかは私にもわかりませんが・・・。
つまりインデックスが有効かどうか、必要なのかどうか、知る手段を知る必要があります。
その中で使われるのがEXPLAIN
構文です。
EXPLAIN構文について知ろう
EXPLAIN
構文は、簡単にいうと、あるクエリを叩いた時に、
- そのクエリはどのような検索方法を使っているか(単純にWHERE
構文なのか、インデックスを使っているのか)
- インデックスが有効であろうカラムはあるのか(あったらどれなのか)
- どのようなインデックスの種類を使われているのか
などがわかるようになります。
このEXPLAIN
構文を使って、最適なインデックスなどを見つけて行くのが良さそうですね。
下記のような感じになります。
EXPLAIN SELECT * FROM Clothes WHERE 'name' = 'タートルネック';
MySQLのEXPLAIN
ここのページではパラメータが表す意味が記載されているので参考にどうぞ。
インデックスが意味をなさないってどういう時?
- そもそも検索で条件として利用されないカラムでインデックスを作成している
- もともと登録している(つまり重複してインデックスを作成している)(主キーは自動的にインデックス作成されることが多いらしいので気をつけましょう)
- 長い文字列に対するインデックス(それに対応するインデックスの種類もあるみたいです)
- 複合インデックスと検索条件で利用するカラムの順番が違う
- データの数が少ない(インデックスで絞っても意味のないくらいのパフォーマンスの改善しか見込めない)
これって、例えばname
にタートルネック
であるデータの数が10件しかない時と10000件ある時とで、だいぶ変わってきます。条件の組み合わせ条件によっては、maker
でソートをしてからname
を調べて検索する、といったことも考えられます。
この際、検索する値としてname
が10件しかなく、かつmaker
が10000件あったとしたら、まずはname
から複合インデックスを定義して、クエリもそれに合わせて作成するのが良いです。
欲しいデータとして該当する行が1行しかない時に
-
maker
で探して10000件 => 該当の行を見つける -
name
で探して10件 => 該当の行を見つける
では明らかに2の方法で探したほうがコストが少なくて楽です。
これを選択性が良い
と表します。(間違っていたらすいません。)
インデックスを作成して、クエリを回す際はこの選択性
を考える必要があるんですね・・・。
執筆途中
Author And Source
この問題について([WIP]SQLアンチパターン-12章 インデックスショットガン-まとめ), 我々は、より多くの情報をここで見つけました https://qiita.com/aaaaanochira/items/a9f13a99cc8a4e5d0c36著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .