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
でのみ機能します 機能。