我正在测试postgresql中jsonb数据类型的性能。每个文档将有大约1500个非分层的密钥。该文件是扁平的。这是表格和文档的样子。
create table ztable0
(
id serial primary key,
data jsonb
)
以下是一份示例文件:
{ "0": 301, "90": 23, "61": 4001, "11": 929} ...
如您所见,文档不包含层次结构,所有值都是整数。但是,有些将来会成为文本。
当搜索键的特定值或按性能执行组时,速度非常慢。这个查询:
select (data ->> '1')::integer, count(*) from ztable0
group by (data ->> '1')::integer
limit 100
花了大约2秒钟完成。有没有办法提高jsonb文档的性能。
答案 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
,作为问题的解决方案,您已经确定了数据存储方式的必要更改,因此beta3
与beta2
不是二进制兼容的。