jsonb 键的长名称是否使用更多存储空间?

dav*_*tgq 8 postgresql json

考虑以下示例:两个表foobar,每个表都有一个 jsonb 列。

  • 对于foo,有一百万行 jsonb 的值是[{"a":123}]

  • 对于bar,有一百万行,其中 jsonb 的值是[{"very_long_key_not_premature_optimization_at_all":123}]

json key inbar比 in 长 46 个字符foo。的大小bar会比 4600 万字节大foo吗?

Eva*_*oll 11

是的,密钥长度很重要

钥匙越大,存放它的空间就越大。JSONB 对键没有任何特殊作用。

测试演员

样本数据

# CREATE TABLE foo AS SELECT '{"f":true}'::jsonb FROM generate_series(1,1e6);
SELECT 1000000

# CREATE TABLE bar AS SELECT '{"very_long_key_not_premature_optimization_at_all":true}'::jsonb FROM generate_series(1,1e6);
SELECT 1000000
Run Code Online (Sandbox Code Playgroud)

桌子尺寸

现在看看表

# \dt+ foo;
                   List of relations
 Schema | Name | Type  |  Owner   | Size  | Description 
--------+------+-------+----------+-------+-------------
 public | foo  | table | ecarroll | 42 MB | 
(1 row)

test=# \dt+ bar;
                   List of relations
 Schema | Name | Type  |  Owner   | Size  | Description 
--------+------+-------+----------+-------+-------------
 public | bar  | table | ecarroll | 89 MB | 
(1 row)
Run Code Online (Sandbox Code Playgroud)

源代码

你可以在这里的源代码中看到它

str = TextDatumGetCString(in_datums[i * 2 + 1]);
len = strlen(str);

v.type = jbvString;

v.val.string.len = len;
Run Code Online (Sandbox Code Playgroud)

ZSON 扩展

您可以考虑查看提供 JSONB 跨行字典压缩的 ZSON 扩展

ZSON 是用于透明 JSONB 压缩的 PostgreSQL 扩展。压缩基于特定 JSONB 文档中最常用的字符串共享字典(不仅是键,还有值、数组元素等)。

在某些情况下,ZSON 可以节省一半的磁盘空间,并为您提供大约 10% 的 TPS。内存也被保存了。请参阅 docs/benchmark.md。不过,一切都取决于您的数据和工作量。不要相信任何基准测试,重新检查您的数据、配置、硬件、工作负载和 PostgreSQL 版本的所有内容。