2016-12-15 21 views
2

私はjsonbフィールドを含むテーブルを持つ9.4 Postgresデータベースを持っています。Postgresを使用したjson配列内のオブジェクト要素のインデックス付け

JSONの構造は次のようになります。

{ 
    name: 'customer1', 
    age: 28, 
    products: [{ 
    name: 'product1', 
    price: 100 
    }, { 
    name: 'product2', 
    price: 200 
    }] 
} 

次のクエリでは、うまく前述のJSONを返す:

SELECT jdoc 
FROM customers, jsonb_array_elements(jdoc->'products') as products 
WHERE (products->>'price')::numeric > 150 

問題は、パフォーマンスはかなり苦しんでいるということですより大きなデータベースで。

このクエリを高速化するために使用できるインデックスは何ですか?私がこれまでに試した何


  • GIN指数(jsonb_opsjsonb_path_ops両方)。彼らは@>のような存在演算子でしか動作しないようです。

  • CREATE INDEX ON persons(((jsonb_array_elements(jdoc->'products')->>'price')::numeric))。私は私にデータ型の不一致エラーを与えます。

    • CREATE INDEX ON persons(((jdoc->'age')::numeric))が機能し、(jdoc->>'age')::numeric < 30を高速に照会できることに注意してください。
+0

JSONではなくリレーショナルデータモデルを使用します。 – Abelisto

答えて

2

あなたが関数を作成して、それを使用することができます

CREATE FUNCTION max_price(jsonb) RETURNS double precision 
    LANGUAGE sql IMMUTABLE AS 
$$SELECT max(p.price) 
FROM jsonb_to_recordset($1->'products') 
     AS p(name text, price double precision)$$; 

CREATE INDEX customers_ind ON customers(max_price(jdoc)); 

次に、このインデックスは、このようなクエリで使用できます。

EXPLAIN SELECT jdoc FROM customers WHERE max_price(jdoc) > 150; 

            QUERY PLAN 
-------------------------------------------------------------------------------- 
Index Scan using customers_ind on customers (cost=0.12..8.14 rows=1 width=36) 
    Index Cond: (max_price(jdoc) > '150'::double precision) 
(2 rows) 

これはあなたのクエリではありません、それは同等でなければなりません。

+0

しかしこれは、値よりも小さい価格を問い合わせたい場合は、 'min(p.price)'を使用する2番目の関数/インデックスを作成する必要があることを意味します。私は正しい? – Kabbalah

+0

はい。これはあなたの質問の特別な場合をターゲットにしています。答えはあなたのような問題がどのように取り組まれているのかをあなたに知らせるべきです。 –

+0

ありがとうございます。私は1日か2日待って、受け入れる前に他のオプションがあるかどうかを確認します。 – Kabbalah

関連する問題