テーブルにインデックスを貼ることの意味

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
あ、データベースの話です。DBです。phpMyAdminです。家にある家具テーブルにインデックスという何やらポストイット的な文房具をはっつけるという意味ではありません。

実際にDBに触れる機会のある人にとってはごく当り前のことかもしれないんですけど、データをSELECT時の検索スピードを上げるために、テーブル内の特定のカラムにインデックスを貼ったりしますよね。プライマリーキーにオートインクリメントをつけると、自動的にPRIMARYのインデックスが貼られるようですが、それ以外は自分で適当なところにインデックスを貼ってあげないといけません。

今まで僕は、インデックスを貼ればSEELCTは速くなる、でもINSERTなどは遅くなるというのを、言葉の上でしか理解してませんでした。どうしてインデックスを貼ると速くなるのか、INSERTのときは遅くなるのか、その理由は分からないけどとにかく速くなったり遅くなったりするんだなと、それだけ覚えていました。

しいて言えば、インデックスを貼ることによりSELECT時には全データを検索しなくてもよくなるんだよと人から言われた言葉を、そっくりそのまま頭の中に入れてはいました。でもその概念は理解できませんでした。インデックスを貼ろうが貼るまいが、全データの中から必要なデータを取得するには全データを洗わないとダメじゃんって思っていたので、インデックスによりそこの何が変わるのかを、分かっていませんでした。

が、つい先日、その辺に(今までよりは)深く触れる機会に出会いまして、どうしてインデックスを貼ると上記のようなことが起こるのか、ようやくその中身がちょっと分かりました。



インデックスの考え方

インデックス…まあ、日本語でいうと、索引、みたいな感じですかね。インデックスを貼るということは、データを索引のように分類すると考えるといいみたいです。

本を開くと、特に参考書とかリファレンスの類には、後ろの方に索引が載ってますよね。アルファベット順に分類されていたり五十音順に分類されていたり、それは本によって違いますが、とにかく頭文字単位で分類されていて、目的の単語が探しやすくなっています。

インデックスを貼ると、その索引が作られるみたいです。

例えば、プライマリーキーとして一般的に使われやすい、一意のIDで考えてみましょうか。種別はint型、数字ってことにします。

すると、新しいデータが登録されるたびに1、2、3…100…200…1000、1001…10000とIDが振られていきますね。

ここにインデックスが貼ってあると、まず各IDの先頭の1桁目を1~9で分類するみたいです。本の索引でいう五十音順ごとの分類と一緒ですね。だからもしこのデータベースが本になったとしたら、後ろの方の索引に

【1】
1 … 1ページ
11 … 2ページ
12 … 2ページ
123 … 13ページ
1001 … 101ページ

【2】
2 … 1ページ
25 … 3ページ
231 … 24ページ

みたいな感じでIDが載っているんでしょうね。あ、ページ数は適当です。本の各ページに10こずつIDが入っていたとしたら、こんな感じの索引になるなっていうただのイメージです。大事なのは、こうやって分類されているんだってこと。



SELECTが速くなるということ

こうやって分類されていれば、たとえばIDが123のデータを検索するときに、全部のデータを見る必要はないわけですね。【1】の中だけを見ればいいことになります。

実際にはもっと細かく、たとえば【1】の中で前から2桁目をさらに0~9に分類して、3桁目もさらに0~9に分類して…と、文字列を1文字ずつ砕いて、グループ化しているようです。

実際にシステムがどうやってその処理を行っているのか、どんな風にデータを索引化して持っているのかはよく分かりませんが、概念としてはこんな感じだそうです。

確かに、こっちの方が検索は早そうですよね。自分で本を読むときだって、1ページずつ順番に見ながら目的の単語を探すよりも、索引を見て目的の単語が載ってるページ数を調べた方が断然早いですもんね。それと同じような感じなんだそうです。

僕が、インデックスを貼ることによりSELECT時の処理が速くなる理由をどうしても理解できなかったのは、これが原因ですね。会社の先輩プログラマにインデックスの話を初めて聞いたとき、本の索引のようなものなんだとは言われましたが、どうやって索引になるねんってずっと思ってました。文字列を1文字単位で分類していたんですね。



INSERTが遅くなるということ

で、何でインデックスを貼るとデータのINSERT時に遅くなるかというと、新しいデータが登録されるたびにこの索引を作り直しているからのようです。

確かに、新しい単語が加われば、本の索引も書き替えなきゃいけないですもんね。それと同じです。

ちなみに、インデックスの使用量…本でいえば、索引に使えるページ数ってところですかね、それには限界があるようで、だからTEXT型のように文字数に制限を持たないようなカラムには、インデックスが効かないようです。


僕自身、そこまで深く理解しているわけではないので、何だかあれな感じの説明になってしまったかもしれませんが、インデックスってのはそういうものなんだそうです。

まあ、このサイトはタイトル検索機能とかついているわけでもないですから、プライマリーキー以外のインデックスをあまり必要とはしていないんですけど、いつか必要になるときが来るかもしれないからね。知っておくことは大事なことだと思います。
 もしかしたら何か関連しているかも? 
 みんなからのコメント 
2017年11月03日 13:47:45
au
最近(2017/10)DBをようやく勉強しだしたものです。まだものすごい基礎もわかりませんが、自分はエンジニアではないので、こういう記事をみると少し勇気づけられました。
2017年11月03日 19:24:13
まっち~(管理人)
ありがとうございます。
僕はエンジニアになって何年も経ちますが、未だに分からないことが多いです。DBは奥が深いっす…。

この記事が何かしらのお役に立てたのなら幸いです。