2017-08-23 12 views
0

データベース(特にPostgreSQL)に「セット」を効率的に保存したいのですが、効率的に行う方法がわかりません。"セット"(python型)をデータベースに効率的に格納する方法は?

心にポップいくつかのオプションがあります:

  • 店は、テキストまたはバイナリ列にリスト({'first item', 2, 3.14})として。これには、データベースに挿入して引き抜くときに構文解析が必要であるという欠点があります。テキスト文字列のセットだけについては、これはかなりうまくいくようであり、解析は最小限です。もっと複雑なものについては、解析は難しくなります。

  • バイナリ列にピクルスとして格納します。これは速くなければならないようだが、それは完全である(何かpicklable作品)が、言語間で移植可能ではない。

  • json(バイナリオブジェクトまたはテキストストリームのいずれか)として格納します。単純なテキストよりも大きな問題ですが、構文解析がよりよく定義されています。

その他のオプションはありますか?誰もこれらの経験がありますか?

答えて

2

テーブル内の行とそのセットのメンバーの間に1対多の関係を保存することです。

解決策のいずれも、SQLによって照会されるセットのメンバーを許可しません。 select * from mytable where 'first item' in mysetのようなことはできません。代わりに、テキスト/ BLOBを取得し、それをデコードまたは解析するために別のプログラミング言語を使用する必要があります。つまり、セットの要素に対してクエリを実行する場合は、毎回フルテーブルスキャンを実行する必要があります。

データベースのいずれかで、あなたがそういうことをさせるのは非常に気にしません。

私はあなたのセットを別のテーブルに分割するべきだと思います。あなたが参照しているテーブルの主キーのインデックス番号がであることを意味しています。また、重複しないようにしたい場合は、小さな余分なスペースは、 + から参照されているテーブルの主キーの要素値です。

設定された要素が異種の型であるように見えるので、数値を何らかの形で正規化している限り、文字列として格納することは問題ありません。

+0

最後のカウントでは、すべてのセットのセットは、600Kの要素を持っています。それを別の列に分割するのは実際には実現可能ではありませんか? –

+0

600K行のテーブルで問題はありません。スペース効率(あなたの質問からはっきりしていなかった)を懸念しているなら、あなたのJSON提案は、ほぼ同じくらいのスペースを取る可能性が高いと思います。 – BoarGules

+0

要素数については、600k * distinct *要素がありますか?そうではなく、テーブルスペースが懸念される場合(または冗長性を避けたい場合)、結合テーブルにIDのリストを格納するだけです。私は2番目の@BoarGulesの引数は、可能であれば、SQLデータをSQLで管理できるようにしてください(JSONはPITAですが、バイナリ形式でデータを格納することは決して問題ありません)。 – Arminius

1

可能な方法の1つは、JSONB配列です。その要素の任意の型を格納することができ、検索速度向上のためにインデックスを作成することができます

create table t as 
    select '["first item", 2, 3.14]'::jsonb as x 
    from generate_series(1,100000); 
insert into t values('["second item", 3, 2.72]'); 
create index idx on t using gin(x); 

explain analyse select * from t where x @> '3'; 
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│             QUERY PLAN             │ 
╞═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on t (cost=36.78..327.18 rows=100 width=47) (actual time=0.055..0.056 rows=1 loops=1)  │ 
│ Recheck Cond: (x @> '3'::jsonb)                    │ 
│ Heap Blocks: exact=1                      │ 
│ -> Bitmap Index Scan on idx (cost=0.00..36.75 rows=100 width=0) (actual time=0.028..0.028 rows=1 loops=1) │ 
│   Index Cond: (x @> '3'::jsonb)                   │ 
│ Planning time: 0.188 ms                      │ 
│ Execution time: 0.121 ms                      │ 
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 

explain analyse select * from t where x @> '[3, "second item"]'; 
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│             QUERY PLAN             │ 
╞═══════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on t (cost=68.78..359.18 rows=100 width=47) (actual time=0.087..0.089 rows=1 loops=1)  │ 
│ Recheck Cond: (x @> '[3, "second item"]'::jsonb)               │ 
│ Heap Blocks: exact=1                      │ 
│ -> Bitmap Index Scan on idx (cost=0.00..68.75 rows=100 width=0) (actual time=0.048..0.048 rows=1 loops=1) │ 
│   Index Cond: (x @> '[3, "second item"]'::jsonb)              │ 
│ Planning time: 0.248 ms                      │ 
│ Execution time: 0.187 ms                      │ 
└───────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 

短所:値によって要素を削除する機能/演算子を使用して何の準備はありません

  • 、インデックスのみで
  • 要素の一意性をチェックするための準備ができた方法はありません。自分で作成する必要があります。

リンク:
JSON Types
jsonb Indexing
JSON Functions and Operators

関連する問題