GINによるJSONBのインデックス化
JSONBドキュメントにGINインデックスを作成し、jsonb_path_opsで包含検索を高速化します。
「GINによるJSONBのインデックス化」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。
JSONBにGINを使う理由
JSONBドキュメントには、多数の「項目」(キーと値の組や配列要素)が含まれます。GIN(Generalised Inverted Index)は、「ドキュメントにXが含まれる行」を検索するクエリに適しています。
デフォルトのGINインデックス
デフォルトの演算子クラスは@>、?、?|、?&に対応します。
CREATE INDEX events_data_gin ON events USING GIN (data);
-- These now use the index:
SELECT * FROM events WHERE data @> '{"type":"login"}';
SELECT * FROM events WHERE data ? 'error';jsonb_path_ops: より小さく高速
包含だけを行うクエリでは、サイズが半分になり高速です。ただし、対応するのは@>だけです。
CREATE INDEX events_data_gin ON events USING GIN (data jsonb_path_ops);
-- Supports @>
-- Does NOT support ? ?| ?&
SELECT * FROM events WHERE data @> '{"type":"login"}';1つのパスだけをインデックス化する
1つのキーだけを検索する場合は、抽出した値に対する式B-treeインデックスの方がさらに高速です。
CREATE INDEX events_user_id_idx
ON events (((data->>'user_id')::BIGINT));
SELECT * FROM events WHERE (data->>'user_id')::BIGINT = 42;配列内部をインデックス化する
配列のパスにGINインデックスを使用します。
CREATE INDEX events_tags_gin
ON events USING GIN ((data->'tags'));
SELECT * FROM events WHERE data->'tags' @> '["admin"]'::JSONB;JSONBインデックスと他のフィルタの組み合わせ
複合述語では、JSONB部分にGINインデックスを使い、JSONB以外の部分には別のインデックスを使えます。
EXPLAIN ANALYZE
SELECT * FROM events
WHERE data @> '{"type":"login"}'
AND ts >= NOW() - INTERVAL '7 days';
-- BitmapAnd: GIN index on data, B-tree on tsGINの書き込み性能
GINの更新はB-treeより負荷が高くなります。書き込みが非常に多いテーブルでは、fastupdateオプションによってGINの更新を保留リストにまとめ、VACUUMでフラッシュできます。
CREATE INDEX events_data_gin ON events USING GIN (data) WITH (fastupdate = on);
-- Flush manually if needed:
SELECT gin_clean_pending_list('events_data_gin');インデックスサイズ
JSONBのGINインデックスは大きくなることがあります。巨大なテーブルでは、次の方法を検討してください。
- 特定のパスだけをインデックス化する(式インデックス)
- 包含だけを行う場合はjsonb_path_opsに切り替える
- 更新の多いフィールドを通常の列に分離する
トライグラムとの組み合わせ
JSONB内部であいまいなテキスト検索を行う場合は、TEXT式に抽出してpg_trgmのGINインデックスを追加します。
CREATE INDEX events_message_trgm
ON events USING GIN ((data->>'message') gin_trgm_ops);インデックスが役に立たない場合
フィルタがすべての行に当たる場合(選択性が非常に低い場合)、インデックスがあってもプランナーはシーケンシャルスキャンを選ぶことがあります。EXPLAIN ANALYZEで確認してください。
JSONBインデックスのメンテナンス
GINインデックスも他のインデックスと同じように肥大化します。定期的にREINDEX CONCURRENTLYを使用してください。
REINDEX INDEX CONCURRENTLY events_data_gin;まとめ
GINにより、JSONBのフィルタ検索をミリ秒単位で実行できます。
- デフォルトのGIN: @>、?、?|、?&
- jsonb_path_ops: より小さく、包含専用
- 抽出したスカラー値に対する式B-tree: 1つのキーに対して最速
理解度チェック
JSONB列に対して、常にdata @> ...だけを検索します。すべての機能に対応しつつ、最もサイズが小さくなるインデックスはどれですか。
よくある質問
「GINによるJSONBのインデックス化」レッスンは無料ですか?
はい。「GINによるJSONBのインデックス化」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。
「GINによるJSONBのインデックス化」で何を学びますか?
JSONBドキュメントにGINインデックスを作成し、jsonb_path_opsで包含検索を高速化します。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
SQL Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「GINによるJSONBのインデックス化」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このSQL Academyレッスンでコードを書いて実行できますか?
はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- JSONBとJSON:使い分け
- パス演算子:->、->>、@>
- GINによるJSONBのインデックス化
- モデリング:JSONBが正規化を上回る場合