sql >> データベース >  >> RDS >> PostgreSQL

JSON配列内の要素を検索するためのインデックス

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




    1. Oracleサブクエリの面白さ

    2. スナップショットレプリケーションを作成する方法

    3. SQLServer2005と一時テーブルスコープ

    4. バックアップ履歴を使用したSQLServerデータベースサイズの増加