インデックスについて
インデックスが分かってない人が非常に多い。
現実にあった例で、60カラムあるテーブルに、前から3つずつの複合インデックスを20個作るとか、30カラムを1つの複合インデックスにするとか、意味が分かっていない人が非常に多くいます。
※ 詳しい人へ。ここでは、インデックス = B-Treeインデックスと考えてください。
インデックスとは
インデックスとは、そのままズバリ「索引」のことです。
身近な例ではカラオケがあります。いわゆるカラオケ本がインデックス。リモコンで押す番号が主キー、流れる音楽・映像が実レコードと考えてみてください。
カラオケ本は「歌手名順」と「曲名順」の2つは最低限あると思います。
これらは、
歌手名順は、「歌手名・曲名」の組み合わせの複合インデックス。
曲名順は、「曲名・歌手名」の組み合わせの複合インデックス。
と考えることができます。
想像してみてください。小学生でも「アンパンマンのマーチ」が歌いたいとき、曲名順を勝手にとって調べないですかね(子供がいないので想像ですが、小学生はアンパンマンはないかもな〜)。逆の本を取ったら調べられないでしょう。
RDBMSの説明には、「オプティマイザが自動で最適なインデックスを選びます」ってなんかすごそうなことを書いていますが、つまりは、「『アンパンマンのマーチ』を探すときには自動で『曲名順のカラオケ本』を使います」程度のことでしかないのです。
そう言われると、全く大したことがないと分かるでしょう。
逆に言うと、インデックスを外すということは「小学生でも間違えないぐらい恥ずかしいことだ!」とも言えますし、「実行計画を見てない」って、どのインデックスを使っているか、使っていないか確認していないということなので「なんてひどいことだ!」って言えるのです。
また、冒頭の前から3つずつとか、30カラムを1つの複合インデックスにするとか、全く意味がないことが分かるでしょう。というよりも、全く意味が分かってない証拠です。私は現場でそういうシステムを見かけるとかなり激昂するのですけれど、意味が分かって(開発費、人月単価を知った上で)現場で見つけると卒倒しそうになるか、激昂する気持ちが理解できますよ(苦笑)。
インデックスのリビルド
RDBMSでは「インデックスのリビルドをした方がいい」とよく言われます。これもカラオケ本をイメージすると簡単に理解できます。
カラオケ本には、新譜は表紙に貼ってあったりしますよね。
カラオケ本を作り直さず、5年分ぐらい新譜が積み重なっていたら、探すのに時間が掛かるようになるでしょう。数ヶ月に1回は作り直されてないと、普通怒るよね。
インデックスのリビルド(再構築)が必要というのはそういうことです。
ある程度のデータが更新されたら、リビルドしないと検索効率は悪くなります。
運用開始から一度もインデックスがリビルドされてない。なんてシステムも珍しくないのですけれど、新譜がx年分貼られたカラオケ本を想像してみてください。プロの仕事としてどうでしょう?
インデックスが多いと更新が遅い
インデックスが多いと更新が遅いというのも、よく言われることです。
これもカラオケ本をイメージすると分かるでしょう。
例えば、「歌手名順」と「曲名順」以外に、「歌詞のフレーズ」があったとしましょう。「歌詞のフレーズ」ごとのカラオケ本を作るとなれば、1曲増える度に新譜リストを作る時間(手間)が掛かりますし、貼り付ける手間も掛かります(パフォーマンスに影響)、物理的な本が大量になります(HDDの容量に影響)、使うときにテーブルに広げるのが大変になります(メモリー容量に影響)
つまり、インデックスを過剰につけると、確かに更新が遅くなりますけれど程度問題です。最近のハードウェア環境では、メモリーが非常に大量にあることが多いので、インデックスを作った方が良いことが多いと思います。(冒頭のような意味がないのは、もちろんNG)
LIKE検索でインデックスを使わないとは
これもカラオケ本はインデックスの塊ですが、カラオケ本で考えてみましょう。
「サザンオールスターズ」の歌を探したいのですが「サザン」がどーしても思い出せなかったとします。(巧い例でなくってスミマセンが隣のヤツに聞くとかなしね)
歌手名順で探すとしても「オールスターズ」で「サザンオールスターズ」を探すには、1ページ目から見ていくしかないですね。つまり、LIKE検索で、一部一致、後方一致の場合はインデックスがあっても使えません。
コンピュータは人間に比べると検索は桁違いに速いのでインデックスを外しても答えが返ってくることはありますが、人間ではものすごい時間が掛かるのと同じように、レコード数によってはインデックスを使った場合の何百、何千倍も時間が掛かります。
逆に「サザン」までは分かっているときは、前方一致になりますので、「サザン」まではインデックスが使えます。カラオケ本でも「サザン」のあとを忘れてても検索できるでしょう。同じことなのです。
LIKE検索は、ハードが高性能であれば便利ですけれど、レコード数や検索頻度の兼ね合いで十分に考慮して設計しないと、将来、大きな問題になることがあります。
インデックスがあっても使わないときもある
20〜25%を超えるとインデックスは非効率というのもよく言われます(ウソ、知らない人が多いけれど、オプティマイザが自動で判断します)
インデックスは索引ですから、今度は書籍の索引で考えてみましょう。
「SQLについて」というSQLについて書かれた本があったとします。
その本で、あなたは「JOIN」について調べたいとします。
どうしますか?
索引でヒットしたページを読みますよね。
その本で、あなたは「SQL」について調べたいとします。
どうしますか?
1ページ目から読んで関係ないと思ったら読み飛ばしますね。
(書籍の場合ヒットしすぎるときは索引を作らないけれど)
つまり、ヒットするページが多いとき(B-Treeインデックスの場合、20〜25%を超えるなら)は、索引を使うより読み飛ばしの方が効率的です。
こんなことは、小学生高学年でも無意識に判断しているレベルですよね。
オプティマイザはそんな判断を自動でしますが、所詮はプログラム。小学校高学年レベルでしかないのです。
SQLは仕様書でオプティマイザはプログラマ
オプティマイザというのは、SQLという言語で書かれた仕様書なら読める小学校高学年レベルの判断力があるプログラマです。レベルの極めて低いプログラマですから、オプティマイザが間違わないように、できるだけオプティマイザに分かり易いSQLを書いて上げないといけないし、出来上がったプログラム(実行計画)は、必ずレビューして上げないといけないわけです。
NoSQLを使うということは、その自動判断する機能を一から作ることになるので、自動判断する機能は必要ないぐらいに単純なシステムでないと大変な工数が掛かる。O/Rマッパーなどを用いて単純なSQLだけで構築するのと、余計なオーバーヘッドが悪影響しパフォーマンスが悪くなります。
オプティマイザは所詮はプログラムですから、決められたことしかできない杓子定規なものです。ベンダーやバージョンによって、多少は性格も異なります。ギリギリまでチューニングしていると、バージョンアップしたら逆に遅くなった。なんてことも極まれに起こります(私は2回ぐらい経験した)。そんな極端なこともありますが、基本的な動きはほとんど同じですから、一つ理解できれば非常に応用が利きます。
とにかく文法よりもイメージが大事
これまで書いてきたとおり、カラオケ本などをイメージして考えると大して難しいモノではないことが分かるでしょう。しかし、SQLにしても、他のプログラミング言語にしても、ほぼ100%イメージを持たずに文法から勉強しているのではないかと思う。特に、他の言語を文法から覚えて、更に、SQLを文法から覚えようとするとギャップが大きすぎて大変難しく感じます。
しかし、まず、イメージがあって、それを文法に置き換える。実行して確認する。という風にして体感的に覚えていけば決して難しくない。
例えば、えらそーに書いていますが、インデックスのリビルドの構文なんて丸っきり覚えていません。覚える気もないから、多分、一生覚えることもないでしょうし、多少の方言の差なんて、最初っから覚えてないので全然気にならないのです。
もう私はボケ老人の域なので、「リビルド」が出てこない可能性も(ないと思うけど)あります。それぐらい、イメージでしか覚えてないのです。でも、インターネットでも、リファレンスでも、すぐに探せます。「リビルド」が出てこなければ、「再作成」でも「再構築」でもやりたいことがイメージできていれば探せるので、全く覚えてないけれど、私は現場で困ることはないです。
オプティマイザという小学校高学年レベルの判断力があるプログラムを一から作ることがどれほど大変なことか……。プログラムを書いたことのある人なら体感的に分かっているでしょう。ですから、オプティマイザの動き、つまり、実行計画を見てその意味が分かり出すと「すごい!賢い!」って感動する人が多く、その辺に気づくとSQLに嵌り出します(笑)。
JOINの仕方から始まって、ここに書いたようなインデックスの話から、こんなSQL http://www.g1sys.co.jp/seminar090515_answer.html まで、一通りを2日間で説明するセミナーをやってます。
7月24日25日に大阪で開催予定です。定員4名なので濃いですよ。参加したいという方は、是非、お問い合わせください。info@g1sys.co.jp