jsonb Postgres9.4以降
バイナリJSONデータ型jsonb インデックスオプションを大幅に改善します。 jsonbにGINインデックスを設定できるようになりました 直接配列:
CREATE TABLE tracks (id serial, artists jsonb); -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);
配列を変換する関数は必要ありません。これはクエリをサポートします:
SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';
@> jsonbであること GINインデックスを使用できる「contains」演算子。 ( jsonではありません 、 jsonbのみ !)
または より特殊な、デフォルト以外のGIN演算子クラス jsonb_path_opsを使用します インデックスの場合:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (artists jsonb_path_ops); -- !
同じクエリ。
現在、 jsonb_path_ops @>のみをサポートします オペレーター。しかし、通常ははるかに小さく、高速です。より多くのインデックスオプションがあります。マニュアルの詳細 。
もし 列artists 例に示されている名前のみを保持しているため、値のみを保存する方が効率的です。 JSONテキストとしてプリミティブ および冗長なキー 列名にすることができます。
JSONオブジェクトとプリミティブタイプの違いに注意してください:
- PostgreSQLのjson配列でインデックスを使用する
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks VALUES (2, '["The Dirty Heads", "Louis Richards"]');
CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames); クエリ:
SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';
?コード> オブジェクトの値では機能しません 、キー および配列要素 。
または:
CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING gin (artistnames jsonb_path_ops);
クエリ:
SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;
名前の重複が多い場合はより効率的です。
json Postgres9.3以降
これはIMMUTABLEで機能するはずです 機能 :
CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';
この機能的なインデックスを作成します :
CREATE INDEX tracks_artists_gin_idx ON tracks
USING gin (json2arr(artists, 'name'));
そして、クエリを使用します このような。 WHEREの式 句はインデックス内の句と一致する必要があります:
SELECT * FROM tracks
WHERE '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));
コメントのフィードバックで更新されました。 配列演算子を使用する必要があります GINインデックスをサポートします。
「に含まれる」演算子<@ この場合。
関数のボラティリティに関する注意
関数をIMMUTABLEで宣言できます json_array_elements()であっても ではありません そうではありませんでした。
ほとんどのJSON 以前はSTABLEのみの関数でした 、 IMMUTABLEではありません 。それを変えるためにハッカーリストで議論がありました。ほとんどがIMMUTABLE 今。確認先:
SELECT p.proname, p.provolatile
FROM pg_proc p
JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = 'pg_catalog'
AND p.proname ~~* '%json%';
機能インデックスは、 IMMUTABLEでのみ機能します 機能。