Postgresql 有效地分组许多字段,包括大文本和jsonb
提前道歉。。。冗长的问题 假设我有一个表Postgresql 有效地分组许多字段,包括大文本和jsonb,postgresql,jsonb,Postgresql,Jsonb,提前道歉。。。冗长的问题 假设我有一个表table_x,其中有20个字段: table_x_id (identity pk) int1 int... int8 text1 text... text8 jsonb1 jsonb2 现在假设我想在表x中保持对分组数据的快速访问(例如,字段int1、int2、text1\u id、text2\u id和jsonb1)。称之为报告1。在提出这个问题时,数据并没有真正发挥重要作用,但这里有一个来自报告1的虚构片段: +------------------
table_x
,其中有20个字段:
table_x_id (identity pk)
int1
int...
int8
text1
text...
text8
jsonb1
jsonb2
现在假设我想在表x
中保持对分组数据的快速访问(例如,字段int1、int2、text1\u id、text2\u id和jsonb1)。称之为报告1
。在提出这个问题时,数据并没有真正发挥重要作用,但这里有一个来自报告1
的虚构片段:
+-----------------------------------------------------------------------+
| int1value int2value text1value text2value jsonb1->item1 jsonb1->item2 |
+-----------------------------------------------------------------------+
| (table_x_id) 12 |
| (table_x_id) 20 |
| (table_x_id) 34 |
+-----------------------------------------------------------------------+
现在假设我有三个或更多这样的报告需求,并且每个报告都涉及到对table_x
中的许多(但不是全部)字段进行分组
每个文本字段可以很容易地达到,比如说,1000个字符,而jsonb字段虽然不大,但只会增加问题
挑战:加快报告分组。
为了加快分组操作并减小表的行大小,我将唯一的文本字段值(确实有很多重叠)拆分为一个单独的text\u表
现在表x
是:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
jsonb_id (identity pk)
jsonb (unique jsonb)
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
在分组方面,我当时考虑在insert/update触发器中使用digest()调用,在表_x
本身中维护相关列的散列。(其思想是将分组中的所有相关字段转换为字符串,将它们连接在一起,并对结果字符串运行哈希。)
现在表x
是:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
jsonb_id (identity pk)
jsonb (unique jsonb)
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
报告现在需要更多的查找,但这很快,现在我只需要按hash1_bytea进行分组,以实现相同的report 1
输出
恐惧:不同行中的等效jsonb字段在按其jsonb::text表示进行比较时可能不等效。据我所知,这些担心似乎是有道理的。
但是,如果我不能以确定的方式将jsonb值转换为文本,我的“表内散列字段”解决方案就会崩溃
然后,我决定在一个单独的jsonb_表
中维护jsonb值,其中我保证任何一行都有一个唯一的jsonb对象
jsonb_表是:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
jsonb_id (identity pk)
jsonb (unique jsonb)
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
对于任何唯一的jsonb对象(在文本中表示时忽略其中对象的顺序),现在在jsonb_表
中只有一行表示它
现在表x
是:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
jsonb_id (identity pk)
jsonb (unique jsonb)
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
是的,维护text_表
和jsonb_表
是一件麻烦事,但这是可行的,而且table_x
现在看起来非常有效,能够快速维护多个散列
看来我已经完成了快速,准确的分组对多种口味的许多领域分组
在这一点上,我要提出两个问题:
我的方法是否合理且设计相对完善?还是有更好的方法来实现我的目标
jsonb1和jsonb2中的json实际上只是一个使用频率较低的特殊键值对数组,但是jsonb1和jsonb2中的数据需要引用完整性,数据保存在规范化的关系表中。在这种情况下,创建一个jsonb_child_表
会是一个坏主意吗
jsonb_child_表是:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
jsonb_id (identity pk)
jsonb (unique jsonb)
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
同样,要确保jsonb_child_表
中的记录是jsonb_表
中jsonb字段的正确分支,也是一件麻烦事,但通过这种方式,我可以:
- 快速维护之前讨论过的所有分组信息
- 保证良好的引用完整性
- 使用
jsonb_child_表
中的字段报告jsonb1(例如),这些字段是通过元数据(通过使用key_lookup_id
的sql连接)排序的(例如),而不是存储在jsonb1本身中
最后一点似乎与我在其他地方读到的内容相呼应,所以。。。在jsonb中维护键值数组需要重新思考。。。如果您想要确保对排序、引用完整性和更快地获取数据,那么jsonb可能是一个糟糕的选择。然而,在我的例子中,维护一个jsonb“header”表(提供一个外键标识字段)允许快速分组不同的值对集合(在table_x
)。因此,我看到了在jsonb(便于分组)和真实表(用于RI和更快、更干净的报告)中维护相同数据的好处
是的,这第二个问题本身值得提出另一个SO问题,但整个问题似乎是相互关联的,所以我在一篇(对不起)长篇文章中介绍了这一切
提前感谢您的反馈 如果您提供一些示例输入数据和基于该数据的预期输出,您的问题将更容易理解。有关如何创建美观的表格的一些提示,请参阅。感谢您提供的好链接。我已经根据您的建议更改了我的示例数据。如果您提供一些示例输入数据和基于该数据的预期输出,您的问题将更容易理解。有关如何创建美观的表格的一些提示,请参阅。感谢您提供的好链接。我已经按照你的建议更改了我的样本数据。