如何有效地在数据库中存储“set”(python类型)?

时间:2017-08-23 20:42:51

标签: python sql json postgresql pickle

我想有效地在数据库(特别是PostgreSQL)中存储“set”,但我不确定如何有效地执行此操作。

有几个选项可供选择:

  • 以文本或二进制列的形式存储为列表({'first item', 2, 3.14})。这具有在插入数据库和拔出时需要解析的缺点。对于仅一组文本字符串,这似乎工作得很好,并且解析是最小的。对于任何更复杂的事情,解析变得困难。

  • 在二进制列中存储为pickle。这似乎应该很快,并且它是完整的(任何可选择的工作),但不能跨语言移植。

  • 以json形式存储(作为二进制对象或文本流)。比纯文本更大的问题,但更好地定义解析。

还有其他选择吗?有没有人有这些经验?

2 个答案:

答案 0 :(得分:2)

您要做的是在表格中的一行与该组成员之间存储一对多的关系。

您的解决方案都不允许SQL查询集合的成员。你不能做select * from mytable where 'first item' in myset之类的事情。相反,您必须检索text / blob并使用另一种编程语言来解码或解析它。这意味着如果你想对集合的元素进行查询,你必须每次都进行全表扫描。

我非常不愿意让你在 my 数据库中做一些类似的事情。

我认为你应该把你的集合分成一个单独的表。我的意思是(因为这显然不像我想象的那么明显),每个元素元素一行,索引你引用的表的主键,或者,如果你不强制执行重复项以一点额外空间为代价,你引用的表的主键 + 设置元素值

由于你的set元素看起来是异构类型,我认为将它们存储为字符串没什么坏处,只要你以某种方式规范化数字。

答案 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