PostgreSQLの9つのインデックスタイプの完全ガイド
Lukas Schneider
DevOps Engineer · Leapcell

PostgreSQLの9つのインデックスタイプの完全ガイド
PostgreSQLは多様なインデックスタイプを提供します。各インデックスタイプは特定のデータ構造と原則に基づいており、異なるアプリケーションシナリオに適しています。以下では、これら9つの主要なインデックスタイプについて詳しく紹介します。
1. B - Treeインデックス
データ構造
B - Tree(バランス多方向探索木)は、自己均衡型の木構造です。その中の各ノードは複数の子ノードを持つことができます(多方向)。通常、B - Treeノードには複数のキーと値のペア、および子ノードへのポインタが含まれています。たとえば、m次のB - Treeノードは最大でm個の子ノードを持ち、少なくとも⌈m/2⌉個の子ノードを持ちます(ルートノードを除く)。
模式図
+--------------------+ | 10 | 20 | 30 | +--------------------+ / | \ +---------+ +---------+ +---------+ | 1 | 5 | | 11 | 15 | | 21 | 25 | +---------+ +---------+ +---------+
原理
B - Treeインデックスは最も一般的に使用されるインデックスタイプであり、ほとんどのデータ型に適しています。そのバランスの取れた木構造により、範囲クエリ、等価クエリ、およびソート操作を効率的に実行できます。クエリを実行するとき、ルートノードから開始し、キー値のサイズの関係に応じて再帰的に下方向に検索し、ターゲットノードが見つかるか、ターゲットが存在しないと判断されるまで続けます。
アプリケーションシナリオ
- 等価クエリ (=): 特定の値を検索する必要がある場合、B - Treeはその値を含むノードをすばやく特定できます。たとえば、ユーザーテーブルで、ユーザーIDが100のユーザーを検索します。
- 範囲クエリ (>, <, >=, <=): 特定の範囲内の値を検索する必要があるクエリの場合、B - Treeはその順序性を利用して、範囲の開始ノードと終了ノードを効率的に特定し、これらのノードを走査して結果を取得できます。たとえば、年齢が20〜30歳のユーザーを検索します。
- ソート操作 (ORDER BY): B - Treeのキー値は順序付けられた方法で格納されているため、インデックスをソートに直接使用でき、データに対する追加のソート操作を回避し、ソート効率を向上させることができます。
作成ステートメント
CREATE INDEX idx_btree ON table_name (column_name);
2. Hashインデックス
データ構造
Hashインデックスは、ハッシュテーブル構造を使用します。ハッシュ関数を介してキー値をハッシュテーブルのスロットにマップします。ハッシュテーブルは通常配列であり、各スロットは1つ以上のキーと値のペアを格納できます。ハッシュの衝突が発生した場合、通常、連結リスト法またはオープンアドレス法を使用して処理します。
模式図
+---+---+---+---+ | 0 | 1 | 2 | 3 | +---+---+---+---+ | | | 10->20| | | | | +---+---+---+---+
原理
Hashインデックスは、ハッシュ関数を介してキー値を固定長のハッシュコードに変換し、ハッシュコードに従って対応するスロットを見つけます。ハッシュ関数はキー値の順序を保証できないため、等価クエリにのみ適しており、範囲クエリやソート操作はサポートしていません。
アプリケーションシナリオ
- 等価クエリ (=): 特定の値を正確に照合する必要がある場合、Hashインデックスはハッシュ関数を介してスロットをすばやく計算し、それによってターゲットデータを見つけることができます。たとえば、キャッシュテーブルで、特定のキャッシュキーに対応する値を検索します。
作成ステートメント
CREATE INDEX idx_hash ON table_name USING hash (column_name);
3. GiSTインデックス
データ構造
GiST(Generalized Search Tree)は、汎用的な検索木構造です。そのノードは、さまざまなタイプのデータと演算子クラスを格納できます。各ノードは通常、複数のキーと値のペアと子ノードへのポインタを含み、異なるデータ型と演算子に応じてカスタマイズされた分割およびマージ操作を実行できます。
模式図
+--------------------+ | Rect1 | Rect2 | | +--------------------+ / | \ +---------+ +---------+ +---------+ | Point1 | | Point2 | | Point3 | +---------+ +---------+ +---------+
原理
GiSTインデックスは、複数のデータ型と演算子クラスをサポートする汎用的なインデックス構造です。データを再帰的にデータ空間を分割することによって木構造に編成し、効率的なクエリを実現します。クエリを実行するとき、クエリ条件と演算子クラスに従って、ルートノードから開始して再帰的に下方向に検索し、条件を満たすノードが見つかるまで続けます。
アプリケーションシナリオ
- フルテキスト検索: テキストデータをトークン化し、GiSTインデックスを使用してこれらのトークンを格納およびクエリできます。たとえば、記事テーブルでキーワード検索を実行します。
- 幾何データクエリ: ポイント、線、平面などの幾何データの場合、GiSTインデックスは、包含や交差などの空間クエリを効率的に処理できます。たとえば、地図アプリケーションで、特定のエリア内のすべての関心のあるポイントを検索します。
- 多次元データクエリ: 多次元配列やベクトルなどの多次元データの処理に適しています。たとえば、機械学習アプリケーションで高次元の特徴ベクトルをクエリします。
作成ステートメント
CREATE INDEX idx_gist ON table_name USING gist (column_name);
4. SP - GiSTインデックス
データ構造
SP - GiST(Space - Partitioned GiST)は、空間分割されたGiSTインデックスです。データ空間を分割することにより、データを木構造に編成します。各ノードには複数のパーティションと子ノードへのポインタが含まれており、パーティションはデータの分布に応じて動的に調整できます。
模式図
+--------------------+ | Part1 | Part2 | | +--------------------+ / | \ +---------+ +---------+ +---------+ | SubP1 | | SubP2 | | SubP3 | +---------+ +---------+ +---------+
原理
SP - GiSTインデックスは、不均衡なデータ分布の処理に適しています。データ空間を分割し、データを異なるノードに均等に分散させることにより、クエリ効率を向上させます。クエリを実行するとき、クエリ条件とパーティション情報に従って、ルートノードから開始して再帰的に下方向に検索し、条件を満たすノードが見つかるまで続けます。
アプリケーションシナリオ
- 多次元データクエリ: 多次元配列やベクトルなどの多次元データの場合、SP - GiSTインデックスはデータの分布に応じてデータを分割し、クエリ効率を向上させることができます。たとえば、地理情報システムで多次元の地理データをクエリします。
- スパースデータクエリ: データセットに大量のスパースデータがある場合、SP - GiSTインデックスはこのデータを効果的に処理し、スパースデータを処理する際の従来のインデックスのパフォーマンスの問題を回避できます。
作成ステートメント
CREATE INDEX idx_spgist ON table_name USING spgist (column_name);
5. GINインデックス
データ構造
GIN(Generalized Inverted Index)は、転置インデックスです。各キー値の出現位置をリストに記録します。具体的には、キー値からドキュメントIDのリストへのマッピングを維持します。ここで、ドキュメントIDは、そのキー値を含むレコードを表します。
模式図
+------+-----------------+ | Key | Document IDs | +------+-----------------+ | A | 1, 3, 5 | | B | 2, 4 | +------+-----------------+
原理
GINインデックスは、複数値の列とフルテキスト検索に適しています。各キー値の出現位置を記録することにより、効率的なクエリを実現します。クエリを実行するとき、クエリ条件に従って、対応するキー値を見つけ、そのキー値を含むドキュメントIDのリストを取得し、それによってターゲットデータを見つけます。
アプリケーションシナリオ
- 配列クエリ: テーブル内の特定の列が配列型である場合、GINインデックスは特定の要素を含む配列を効率的にクエリできます。たとえば、製品テーブルで特定のタグを含む製品を検索します。
- JSONデータクエリ: JSONデータの場合、GINインデックスはJSONのキーと値のペアをインデックス付けできるため、効率的なJSONデータクエリを実現できます。たとえば、ユーザーテーブルで特定の属性を持つユーザーを検索します。
- フルテキスト検索: GINインデックスはテキストデータをトークン化し、各トークンの出現位置を記録できるため、効率的なフルテキスト検索を実現できます。たとえば、ニューステーブルでキーワード検索を実行します。
作成ステートメント
CREATE INDEX idx_gin ON table_name USING gin (column_name);
6. BRINインデックス
データ構造
BRIN(Block Range INdex)は、ブロック範囲インデックスです。各データブロックの最小値と最大値を格納することにより、インデックスのサイズを縮小します。インデックスファイルは一連のブロック範囲エントリで構成されており、各エントリには、データブロックの開始ブロック番号、終了ブロック番号、最小値、および最大値が含まれています。
模式図
+--------------------+ | Block Range | Min | Max | +--------------------+ | 0 - 10 | 1 | 10 | | 11 - 20 | 11 | 20 | +--------------------+
原理
BRINインデックスは、非常に大きなテーブルに適しています。各ブロック範囲の最小値と最大値を格納することにより、クエリを実行するときに、クエリ条件を満たすデータがデータブロックに含まれている可能性があるかどうかをすばやく判断し、スキャンする必要があるデータブロックの数を減らすことができます。ただし、ブロック範囲の境界情報のみを記録するため、クエリのパフォーマンスは比較的低くなります。
アプリケーションシナリオ
- 非常に大きなテーブル: テーブルに大量のデータがある場合、BRINインデックスを使用すると、インデックスのストレージスペースを大幅に削減し、インデックスのメンテナンス効率を向上させることができます。たとえば、ログテーブルに大量のログレコードを格納します。
- 順序で挿入されたデータ: データが順序で挿入された場合、隣接するデータブロック内のデータには特定の順序があり、BRINインデックスはより良い役割を果たすことができます。たとえば、時系列データでは、時系列順に挿入されたデータは、BRINインデックスを使用して効率的にクエリできます。
作成ステートメント
CREATE INDEX idx_brin ON table_name USING brin (column_name);
7. Bitmapインデックス
データ構造
Bitmapインデックスは、ビットマップ構造を使用します。異なるキー値ごとに、ビットマップを維持し、ビットマップの各ビットはレコードに対応します。ビットが1の場合、対応するレコードにそのキー値が含まれていることを意味します。0の場合は、含まれていないことを意味します。
模式図
+------+--------------------+ | Key | Bitmap | +------+--------------------+ | A | 1 0 1 0 1 | | B | 0 1 0 1 0 | +------+--------------------+
原理
Bitmapインデックスは、カーディナリティが低い列(つまり、列に異なる値が少ない)に適しています。ビットマップのビット演算を介して、複数条件の効率的な結合クエリを実現します。クエリを実行するとき、クエリ条件に従って、対応するビットマップを見つけ、次にビット演算を実行して条件を満たすレコードのビットマップを取得し、最後にビットマップに従ってターゲットデータを見つけます。
アプリケーションシナリオ
- カーディナリティの低い列: 列に異なる値が少ない場合、Bitmapインデックスを使用すると、インデックスのストレージスペースを大幅に削減し、クエリ効率を向上させることができます。たとえば、性別列には、「男性」と「女性」の2つの値しかありません。
- 複数条件の結合クエリ: Bitmapインデックスは、複数条件の結合クエリに非常に効果的です。これは、ビット演算を介して複数条件のビットマップをすばやくマージして、最終的なクエリ結果を取得できるためです。たとえば、ユーザーテーブルで、女性であり、年齢が20〜30歳のユーザーを検索します。
作成ステートメント
-- PostgreSQL自体には、Bitmapインデックスを作成するための直接的な構文はありませんが、B - Treeインデックスを組み合わせることによって、同様の効果を実現できます CREATE INDEX idx_bitmap ON table_name (column_name);
8. Partialインデックス
データ構造
Partialインデックスのデータ構造は、一般的なインデックスの構造と同じですが、テーブル内の一部のデータに対してのみインデックスを作成する点が異なります。条件式を追加することにより、条件を満たすデータのみが含まれます。
模式図
元のテーブル: +----+-------+ | ID | Value | +----+-------+ | 1 | A | | 2 | B | | 3 | A | +----+-------+ Partialインデックス (Value = 'A'): +----+-------+ | ID | Value | +----+-------+ | 1 | A | | 3 | A | +----+-------+
原理
Partialインデックスは、データの一部に対してのみインデックスを作成することにより、インデックスのサイズとメンテナンスコストを削減し、インデックスの効率を向上させます。クエリを実行するとき、条件を満たすデータのみがインデックス付けされるため、不要なインデックススキャンが削減されます。
アプリケーションシナリオ
- データの一部のみをインデックス付けする: テーブル内の一部のデータのみをインデックス付けする必要がある場合は、Partialインデックスを使用できます。たとえば、ユーザーテーブルで、アクティブなユーザーのみをインデックス付けします。
- インデックス効率の向上: インデックス内のデータ量を削減することにより、Partialインデックスはインデックスのクエリおよびメンテナンス効率を向上させることができます。たとえば、ログテーブルで、最新の月のログのみをインデックス付けします。
作成ステートメント
CREATE INDEX idx_partial ON table_name (column_name) WHERE condition;
9. Uniqueインデックス
データ構造
Uniqueインデックスのデータ構造は、一般的なインデックスの構造と同じであり、通常はB - Treeまたはその他の適切なインデックス構造を使用します。その特徴は、インデックス列のすべての値が一意であることを保証することです。
模式図
+----+-------+ | ID | Value | +----+-------+ | 1 | A | | 2 | B | | 3 | C | +----+-------+
原理
Uniqueインデックスは、データを挿入または更新するときに、インデックス列の値が一意であるかどうかをチェックして、インデックス列のすべての値が一意であることを保証します。一意性制約に違反すると、操作は拒否されます。
アプリケーションシナリオ
- 主キー制約: Uniqueインデックスを使用して、主キー制約を実装し、テーブル内の各行に一意の識別子があることを保証できます。たとえば、ユーザーテーブルでユーザーIDを主キーとして使用します。
- 一意性制約: 特定の列の値が一意である必要があるが、主キーではない場合は、Uniqueインデックスを使用できます。たとえば、メールテーブルでメールアドレスを一意性制約として使用します。
作成ステートメント
CREATE UNIQUE INDEX idx_unique ON table_name (column_name);
Leapcell:最高のサーバーレスWebホスティング
最後に、Webサービスのデプロイに最適なプラットフォームをお勧めします:Leapcell
🚀 お気に入りの言語で構築
JavaScript、Python、Go、またはRustで簡単に開発できます。
🌍 無制限のプロジェクトを無料でデプロイ
使用した分だけ支払います。リクエストも料金もありません。
⚡ 従量課金制、隠れたコストなし
アイドル料金は不要で、シームレスなスケーラビリティを実現します。
🔹 Twitterでフォローしてください:@LeapcellHQ