随着密钥数量的增加,JSONB性能会下降

时间:2014-10-08 14:25:36

标签: sql json postgresql jsonb

我正在测试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文档的性能。

1 个答案:

答案 0 :(得分:5)

这是9.4beta2中的一个已知问题,请看一下这个blog post,它包含一些细节和指向邮件线程的指针。

关于这个问题。

PostgreSQL是using TOAST来存储数据值,这意味着大值(通常为2kB或更大)存储在单独的特殊表中。 PostgreSQL还尝试使用它的pglz方法压缩数据(已存在多年)。通过“尝试”意味着在决定压缩数据之前,首先探测1k字节。如果结果不令人满意,即压缩对探测数据没有任何好处,则决定不压缩。

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

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

修复

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

虽然花了大约一个月才修好。正如我所看到的那样,9.4beta3已经already tagged,因此您可以在正式公布之后尽快重新测试。

重要提示:您必须pg_dump / pg_restore行使或使用pg_upgrade工具切换到9.4beta3,作为问题的解决方案,您已经确定了数据存储方式的必要更改,因此beta3beta2不是二进制兼容的。