さて、PostgreSQLの世界にはいくつかのインデックスがあって、それぞれが自分の役割を持ってるんだ。乗り物を選ぶのと同じで、公園をサイクリングするなら自転車、街の反対側に行くなら車、みたいな感じ。インデックスも用途によって使い分けるのが大事!
PostgreSQLでよく使うインデックスはこんな感じ:
B-TREEインデックス: ほとんどの用途に使える万能型。HASHインデックス: 完全一致の検索に特化。GINインデックス: 配列やJSONBの検索に最適。GiSTインデックス: 地理情報みたいな複雑なデータ型に使う。
インデックスは検索を速くするためのもの。4つの最適化タイプがあって、それぞれ得意な操作やデータ型が違うんだ。
インデックス自体を細かくコントロールすることはできない。できるのは、インデックスタイプを選ぶことだけ。無しか、上で紹介したどれか。これからそれぞれの特徴と使いどきを見ていこう!
B-TREEインデックス
B-TREE("balanced tree"の略)は一番よく使われるインデックスで、PostgreSQLの基本。データをツリー構造で整理して、検索・ソート・フィルタを速くしてくれる。
本棚をイメージしてみて。棚ごとに本がアルファベット順に並んでる。例えば「M」の本を探すなら、全部の本を順番に見る必要はなくて、真ん中から探し始めればいい。バランスの取れた木構造も同じ考え方だよ。
どんな時に使う?
ほぼいつでもOK!B-TREEインデックスは特に:
- 範囲検索:
WHERE price > 100 - ソート:
ORDER BY name ASC - 完全一致検索:
WHERE id = 42
作り方の例:
-- productsテーブルのpriceカラムにB-TREEインデックスを作成:
CREATE INDEX idx_price ON products(price);
これで、WHERE price > 100みたいなクエリを書くと、PostgreSQLはこのインデックスを使って全件検索しなくて済むようになるよ。
HASHインデックス
HASHインデックスはハッシュテーブルを使って高速検索するタイプ。強みは値の完全一致比較。でもHASHインデックスには制限があって、範囲検索やソートには使えない。
イメージとしては、番号付きのカードが並んでるカードボックス。42番のカードを探すなら一瞬。でも「40から50までのカードを見せて」と言われたら無理。
HASHインデックスは完全一致検索専用:
WHERE email = 'user@example.com'SELECT ... WHERE id = 123
範囲やソートが必要ならHASHは向いてない。
作成例:
-- usersテーブルのemailカラムにハッシュインデックスを作成:
CREATE INDEX idx_email_hash ON users USING HASH (email);
これで、WHERE email = 'user@example.com'みたいなクエリでこのインデックスが使われるよ。
注意:HASHインデックスは特殊なケース向けで、B-TREEより使う場面は少なめ。
GINインデックス(Generalized Inverted Index)
GINは配列やJSONB、テキストデータで本領発揮する特殊なインデックス。例えば、何千個も引き出しがある棚を想像してみて。それぞれの引き出しに「りんご」とか「バナナ」ってラベルが貼ってあって、「りんご」ならその引き出しだけ見ればOK。全部探す必要はない。
GINインデックスが必要なのは:
- 配列検索:
@>(含む)、<@(含まれる) - JSONBデータ:
WHERE jsonb_data @> '{"key": "value"}'
作成例
-- 配列を持つtagsカラムにGINインデックスを作成:
CREATE INDEX idx_tags_gin ON products USING GIN (tags);
これで、例えば「エレクトロニクス」と「おすすめ」がタグになってる商品を効率よく探せるようになる。
GiSTインデックス(Generalized Search Tree)
GiSTインデックスは、地理座標や範囲みたいな複雑なデータ型に強い。空間検索や範囲検索に最適化されたツリーを作る。
例えば、地図上で座標ごとにポイントがマークされてて、「今いる場所から半径5km以内のポイントを探す」みたいなことがすぐできる。
GiSTが向いてるのは:
- 地理データ:
SELECT ... FROM locations WHERE ST_DWithin(geom, point, distance) - 範囲検索:
WHERE date_range && '[2023-01-01, 2023-12-31]'
作成例:
-- 地理データを持つlocationカラムにGiSTインデックスを作成:
CREATE INDEX idx_location_gist ON places USING GiST (location);
これで、近くのポイントを探すみたいな複雑な地理クエリもサクッとできる。
インデックス比較表
| インデックスタイプ | 得意な用途 | 使用例 | メモ |
|---|---|---|---|
B-TREE |
範囲検索、ソート | price > 100, ORDER BY name ASC |
万能インデックス。 |
HASH |
完全一致チェック | email = 'user@example.com', id = 42 |
範囲検索は不可。 |
GIN |
配列、JSONB | tags @> '{tech}', jsonb_data @> '{"key": "value"}' |
複雑データに速い。 |
GiST |
地理、範囲、距離 | ST_DWithin(geom, point, distance) |
地理データ用。 |
これでPostgreSQLの主なインデックスタイプと使い方がわかったね。インデックス選びは戦略的な一手。クエリの速さはここで決まる!詰み、遅延バイバイ!
GO TO FULL VERSION