5

tl;dr

PSQL 9.4 を使用して、虚数関数を使用する場合のように、jsonb フィールドから複数の値を取得する方法はありますか。

jsonb_extract_path(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key'])

複数の値を選択するのに必要なほぼ直線的な時間 (1 つの値 = 300 ミリ秒、2 つの値 = 450 ミリ秒、3 つの値 = 600 ミリ秒) を高速化することを期待して

バックグラウンド

次のjsonbテーブルがあります:

CREATE TABLE "public"."analysis" (
  "date" date NOT NULL,
  "name" character varying (10) NOT NULL,
  "country" character (3) NOT NULL,
  "x" jsonb,
  PRIMARY KEY(date,name)
);

約 100 000 行あり、各行には 90 以上のキーと対応する値を持つ jsonb 辞書があります。かなり迅速な方法 (< 500 ミリ秒) でいくつか (< 10) のキーと値を選択する SQL クエリを作成しようとしています。

インデックスとクエリ: 190ms

私はインデックスを追加することから始めました:

CREATE INDEX ON analysis USING GIN (x);

これにより、次のように "x" ディクショナリの値に基づくクエリが高速になります。

SELECT date, name, country FROM analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;

これには約 190 ミリ秒かかります (許容範囲)

ディクショナリ値の取得

ただし、SELECT 部分で戻るキーを追加し始めると、実行時間はほぼ直線的に増加します。

1値:300ms

select jsonb_extract_path(x, 'a_dictionary_key') from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;

366ms (+175ms)

select x#>'{a_dictionary_key}' as gear_down_altitude from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100 ;

300ms (+110ms)

3値:600ms

select jsonb_extract_path(x, 'a_dictionary_key'), jsonb_extract_path(x, 'a_second_dictionary_key'), jsonb_extract_path(x, 'a_third_dictionary_key') from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;

600ミリ秒かかります(選択した値ごとに+410または+100)

select x#>'{a_dictionary_key}' as a_dictionary_key, x#>'{a_second_dictionary_key}' as a_second_dictionary_key, x#>'{a_third_dictionary_key}' as a_third_dictionary_key from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100 ;

600ミリ秒かかります(選択した値ごとに+410または+100)

より多くの値をより速く取得する

虚数関数を使用する場合のように、jsonb フィールドから複数の値を取得する方法はありますか。

jsonb_extract_path(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key'])

これにより、これらの検索が高速化される可能性があります。それらを列、リスト/配列、さらにはjsonオブジェクトとして返すことができます。

PL/Python を使用して配列を取得する

念のため、PL/Python を使用してカスタム関数を作成しましたが、おそらく json.loads が原因で、かなり遅くなりました (5 秒以上)。

CREATE OR REPLACE FUNCTION retrieve_objects(data jsonb, k VARCHAR[])
RETURNS TEXT[] AS $$
  if not data:
    return []

  import simplejson as json
  j = json.loads(data) 

  l = []
  for i in k:
    l.append(j[i])

  return l

$$ LANGUAGE plpython2u;

# Usage:
# select retrieve_objects(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key']) from analysis  where date > '2014-01-01' and date < '2014-05-01' 

2015-05-21 更新

GIN インデックスで hstore を使用してテーブルを再実装しましたが、パフォーマンスは jsonb を使用した場合とほぼ同じです。つまり、私の場合は役に立ちません。

4

2 に答える 2