もうインデックスに触れたことあるよね。今日はしっかりインデックスについてやっていくから、仕組みをちゃんと理解できるようになるよ。インデックスってマジで便利で、クエリを何百倍、何千倍も速くできる。きっと気に入るはず。でも、インデックスってそもそも何?
例えば、めっちゃでかい図書館で欲しい本を探すとする。何の順番もなかったら、探すのに永遠かかるよね。だから本は普通、アルファベット順とかカテゴリで並んでる。データベースのインデックスも同じ感じで動くんだ。
ちゃんと説明すると、インデックスは、テーブル内の行を素早く探すために作られた特別な追加データ構造だよ。 必要な情報を見つけるためにチェックしなきゃいけないデータ量を減らしてくれる。
ある意味、インデックスは百科事典の目次みたいなもの。もし本自体がテーブルだとしたら、
最初から最後まで全部読む代わりに、目次を使って一発で目的のページに飛べるよね。
例えば、employeesテーブルに10万件の社員データがあるとする。もし「ミン」って名字の社員を探すなら、インデックスがなかったら全部のレコードを見ないといけない(めっちゃ時間かかる)。でもインデックスがあれば、Postgresはどこを見ればいいかすぐ分かるから、検索が超速くなる。
インデックスってどうやって動くの?
インデックスがクエリを速くする仕組みを知るには、裏側で何が起きてるかを理解しないとね。インデックスはテーブルの1つ以上のカラムを元に作られて、検索しやすい構造にデータを整理してくれる。
PostgreSQLのインデックスは、だいたいB-Tree(バランス木)っていうデータ構造を使ってる。ざっくり説明すると:
- インデックス作成: インデックスを作るカラムのデータが木構造に整理される。
- 検索時: PostgreSQLはインデックスを使って、必要な行を一瞬で見つける。テーブル全体をスキャンしなくてOK。
- 木の構造: 木は順番に並んでるから、次のレコードに素早く移動できる(二分探索アルゴリズム)。
例:100万行あるテーブルがあるとする。インデックスなしだと100万件全部チェックしないといけない。インデックスありなら、PostgreSQLは数十件だけ見ればOK。
インデックスはいつ使うべき?
インデックスは読み取り系の操作、例えば検索・フィルタ・ソートをめっちゃ速くしてくれる。でもその代わり、書き込み系の操作(INSERT、UPDATE、DELETEとか)はちょっと遅くなる。なぜなら、データが変わるたびにインデックスも更新しなきゃいけないから。
インデックスが必須なシーン
検索が多い場合: 特定の値でよく検索するなら、例えば:
SELECT * FROM employees WHERE last_name = 'ミン';
データのフィルタ: WHEREやHAVINGで条件を使うとき:
SELECT * FROM employees WHERE salary > 50000;
データのソート: ORDER BYを使うとき:
SELECT * FROM employees ORDER BY hire_date DESC;
テーブルの結合(JOIN): 特定のカラムでよくテーブルを結合する場合。
*いつ*インデックスを使わない方がいい場合
- テーブルがめっちゃ小さい(例えば10〜50行)なら、インデックスの効果はほぼない。
- インデックスを作るカラムがクエリでほとんど使われない場合。
- カラムの値がほとんどユニークじゃない(例えば
genderカラムで2〜3種類しか値がない)場合。
例:statusカラムに「アクティブ」と「非アクティブ」しかない場合、インデックスを作っても意味ないよ。
インデックスのパフォーマンスへの影響
もう分かったと思うけど、インデックスは読み取りクエリを爆速にする。でも書き込み操作は遅くなることもある。理由は、行を追加・更新・削除するたびに、PostgreSQLがインデックス情報も更新しなきゃいけないから。
インデックスとパフォーマンスのバランス
- よく更新されるテーブルは、インデックスの数を増やしすぎないように注意しよう。
- 読み取りがメインのテーブルなら、インデックスは必須。
インデックスのリアルなメリット
実際、インデックスはこんな場面で大活躍:
- Webアプリの最適化: SQLクエリが速くなるから、ページの表示も爆速になる。
- 巨大テーブルの操作: インデックスなしだと、何百万行もあるテーブルへのクエリは何分もかかることも。
- スケーラビリティ: インデックスがあれば、データ量が増えても効率よく処理できる。
例えば、商品や注文データを持つネットショップのデータベースは、インデックスなしじゃやってられない。なかったら、ユーザーはページが表示されるまで何年も待つことになるよ。
GO TO FULL VERSION