【问题标题】:How to store a "set" (the python type) in a database efficiently?如何有效地将“集合”(python 类型)存储在数据库中?
【发布时间】:2017-08-23 20:42:50
【问题描述】:

我想有效地将​​“集合”存储在数据库(特别是 PostgreSQL)中,但我不确定如何有效地做到这一点。

我想到了几个选项:

  • 在文本或二进制列中存储为列表 ({'first item', 2, 3.14})。这具有在插入数据库和拉出时需要解析的缺点。仅对于文本字符串集,这似乎工作得很好,并且解析很少。对于更复杂的东西,解析变得困难。

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

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

还有其他选择吗?有没有人有这方面的经验?

【问题讨论】:

    标签: python sql json postgresql pickle


    【解决方案1】:

    您要做的是在表中的一行和集合的成员之间存储一对多的关系。

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

    我很不情愿让你在一个我的 数据库中做类似的事情。

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

    由于您的 set 元素似乎属于异构类型,我认为将它们存储为字符串并没有什么坏处,只要您以某种方式规范化数字即可。

    【讨论】:

    • 最后统计,所有集合的集合有 600k 个元素。把它分成不同的列是不可行的,是吗?
    • 我认为 600K 行的表没有问题。如果您担心空间效率(您的问题并不清楚),那么我认为您的 JSON 提案可能会占用几乎同样多的空间。
    • 关于元素的数量,你有 600k distinct 元素吗?如果不是并且您担心表空间(或希望避免冗余),您可以只将 ID 列表存储在连接表中。我第二个 @BoarGules 参数,如果可能的话,尽量让 SQL 数据在 SQL 中易于管理(JSON 是 PITA,但以二进制形式存储数据是绝对不行的)。
    • OP 说“所有集合的集合有 600k 个元素”,所以我认为这意味着不同。因此,我们可以计算出每字节平均元素长度大约为 1MB 的表。不可怕。
    【解决方案2】:

    一种可能的方式是 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

    【讨论】:

      猜你喜欢
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 2021-04-11
      • 1970-01-01
      相关资源
      最近更新 更多