4

我正在 postgresql 中测试 jsonb 数据类型的性能。每个文档将有大约 1500 个非分层键。文档被展平。这是表格和文档的样子。

create table ztable0
(
   id serial primary key,
   data jsonb
)

这是一个示例文档:

{ "0": 301, "90": 23, "61": 4001, "11": 929} ...

如您所见,该文档不包含层次结构,所有值都是整数。但是,有些将来会是文本。

  • 行数:86,000
  • 列数:2
  • 文档中的键:1500+

当搜索某个键的特定值或按组执行时,性能非常缓慢。这个查询:

select (data ->> '1')::integer, count(*) from ztable0
group by (data ->> '1')::integer
limit 100

大约需要 2 秒才能完成。有什么方法可以提高 jsonb 文档的性能。

4

1 回答 1

5

这是 中的一个已知问题9.4beta2,请查看此博客文章,其中包含一些详细信息和指向邮件线程的指针。

关于问题。

PostgreSQL使用 TOAST来存储数据值,这意味着大值(通常大约 2kB 或更多)存储在单独的特殊类型的表中。而且 PostgreSQL 还尝试使用它的pglz方法来压缩数据(已经存在了很长时间)。“尝试”意味着在决定压缩数据之前,先探查前 1k 字节。如果结果不令人满意,即压缩对探测数据没有好处,则决定不压缩。

因此,初始 JSONB 格式在其值的开头存储了一个偏移量表。对于 JSON 中具有大量根键的值,这会导致前 1kB(以及更多)被偏移量占用。这是一系列不同的数据,即不可能找到两个相等的相邻 4 字节序列。因此没有压缩。

请注意,如果一个人会通过偏移表,则该值的其余部分是完全可压缩的。因此,一种选择是明确地告诉pglz代码压缩是否适用以及在哪里探测它(特别是对于新引入的数据类型),但现有的基础设施不支持这一点。

修复

因此决定更改数据在 JSONB 值中的存储方式,使其更适合pglz压缩。这是Tom Lane 的提交消息,其中包含实现新 JSONB 磁盘格式的更改。尽管格式发生了变化,但随机元素的查找仍然是 O(1)。

不过花了大约一个月的时间才修好。如我所见,9.4beta3已经被标记为 ,所以你很快就可以在官方宣布后重新测试它。

重要提示:您必须执行pg_dump/pg_restore练习或使用pg_upgrade工具来切换到9.4beta3,以解决您确定需要更改数据存储方式的问题,因此beta3二进制文件与beta2.

于 2014-10-08T15:11:14.467 回答