データベースのパフォーマンスを高めるインデックス

はじめに
ITとは「情報技術」のことを指します。IT関連のあらゆるテクノロジーは、情報つまりは”データ”を、より効果的に扱うための手段だと言えます。
それだけに、データはシステムの中心にある最も重要な存在だといっても過言ではありません。そして、そのデータを管理し、活用するための土台となるのがデータベース(DB)です。
この記事は、データベースについて学んだことを、自分なりに整理した備忘録です。
同じように勉強している方の参考にもなれば嬉しいです。
インデックスとは
インデックスは、データベースで対象データを効率よく探すための仕組みです。SQLの処理を速くするためのチューニングでも、よく使われます。

インデックスの役割としては、「本の巻末にある索引」をイメージしてもらえれば分かりやすいと思います。調べたい言葉がどのページに載っているか分かれば、最初からすべてのページを読む必要はありません。
データベースのインデックスも、基本的には「キーとなる値」と「データの場所を示す情報(ポインタ)」を組み合わせたものです。本の索引と同じように、目的のデータを探す手がかりになります。
B-treeインデックスの特徴
インデックスにはいくつかの種類がありますが、まずは汎用性の高い「B-treeインデックス」を覚えておけば十分です。

B-treeインデックスは「平衡木」なので、入口にあたる「ルート」から末端の「リーフ」までの距離が、どの経路でも同じになっています。そのため、どの経路をたどっても処理が完了するまでの時間は大きく変わりません。
また、リーフに保存された値はソートして保持しているため、SQLのORDER BY句などでインデックスの順序をそのまま利用できる場合は、別途並べ替える手間を省けます。
どのような列にインデックスを作るか
インデックスの数が多いほどデータベースのパフォーマンスが上がるわけではありません。適切なテーブル・カラムに作ることで、はじめてインデックスが有効に活用できます。B-treeインデックスを作るときは、以下の3点に着目します。
データ量の多いテーブル
データ量が少ないテーブルでは、インデックスを使うよりも、テーブル全体を読み取る「フルスキャン」の方が速い場合があります。参考図書では、目安として10万レコードが挙げられています。
カーディナリティの高い列
カーディナリティとは、列に含まれる値の種類の多さを指します。例えば、会員ごとに異なる「会員ID」はカーディナリティが高く、無料/有料の2種類しかない「会員区分」は低いと言えます。
さらに、値が特定の種類に偏らず、なるべく均等に分散していることも重要です。
上記の例で考えると、会員の「登録日」は最大で365通り存在します。このサービスの会員が1万人いた場合、会員の99%が特定の登録日に集中していると、その登録日で検索しても9,900人がヒットしてしまうためあまり意味がありません。一方で全日付に均等に分散していれば、1日当たりの会員は約27人となり、全体の0.3%程度に絞り込めるためインデックスの効果を期待できます。
WHERE句や結合条件に使う列
当然のことですが、検索や結合、並べ替えなどに使う予定のない列にインデックスを作っても、処理を速くする効果は期待できません。実際のSQLで使う列かどうかも確認する必要があります。
インデックスを作るときの注意点
主キーや一意制約のインデックスと重複させない
主キーや一意制約を設定した列には、多くのデータベースでインデックスがすでに用意されています。そのため、同じ列構成のインデックスを重ねて作る必要はありません。
データの更新に負荷がかかる
インデックスは検索を速くする一方で、データの追加・変更・削除に伴い、インデックス自体も更新する必要があります。インデックスが増えるほど、その維持にかかる負荷も増えるため、その負荷も考慮して検討することが大切です。
さいごに
今回は『達人に学ぶDB設計徹底指南書』を参考に、データベースのパフォーマンスに関わるインデックスについてざっくりまとめました。
今までは割とイメージしやすい内容が多かった印象ですが、インデックスはなかなか中級者向けというか、個人的には少し難しい内容でした。ただ、DBを扱う以上避けては通れないものなので、好き嫌いせず学んでいきたいですね…。
次回は、同じくデータベースのパフォーマンスに関わる統計情報について解説していきます。



