PostgreSQL 刚刚推出了 JSONB,它已经成为趋势 on hacker news。它与以前存在于 PostgreSQL 中的 Hstore 和 JSON 有何不同?
它的优点和局限性是什么?什么时候应该考虑使用它?
首先,hstore
是一个 contrib 模块,它只允许您存储 key =>;值对,其中键和值只能是 text
(但值也可以是 sql NULL
)。
json
和jsonb
允许您存储有效的 JSON 值(在其 spec 中定义)。
前任这些是有效的 JSON 表示:null
、true
、[1,false,"string",{"foo":"bar"}]
、{"foo":"bar","baz":[null]}
- hstore
与 JSON 的能力相比只是一个小子集(但如果您只需要这个子集,也可以)。
json
& 之间的唯一区别jsonb
是他们的存储:
json 以纯文本格式存储,而
jsonb 以某种二进制表示形式存储
这样做有3个主要后果:
jsonb 通常比 json 需要更多的磁盘空间来存储(有时不会)
jsonb 从其输入表示构建比 json 花费更多时间
json 操作比 jsonb 花费的时间要多得多(每次对 json 类型的值进行一些操作时,也需要进行解析)
当 jsonb
可用于稳定版本时,将有两个主要用例,您可以轻松地在它们之间进行选择:
如果您只在应用程序中使用 JSON 表示,PostgreSQL 仅用于存储和检索此表示,您应该使用 json。如果你在 PostgreSQL 中对 JSON 值做了很多操作,或者对一些 JSON 字段使用索引,你应该使用 jsonb。
皮尤什:
简短的回答是:
如果您在 PostgreSQL 内部进行大量 JSON 操作,例如排序、切片、拼接等,出于速度原因,您应该使用 JSONB。
如果您需要对 JSON 上的任意键搜索进行索引查找,那么您应该使用 JSONB。
如果您没有执行上述任何操作,您可能应该使用 JSON。
如果您需要保留键顺序、空格和重复键,则应使用 JSON。
要获得更长的答案,您需要等待我在接近 9.4 版本时完成完整的“HowTo”写作。
json和jsonb(original image by PostgresProfessional)区别的简单说明:
SELECT '{"c":0, "a":2,"a":1}'::json, '{"c":0, "a":2,"a":1}'::jsonb;
json | jsonb
------------------------+---------------------
{"c":0, "a":2,"a":1} | {"a": 1, "c": 0}
(1 row)
json:文本存储«原样»
jsonb:没有空格
jsonb:没有重复的键,最后一个键获胜
jsonb:键已排序
jsonb 开发人员在 speech video 和 slide show presentation 中的更多内容。他们还介绍了 JsQuery,这是一个提供强大 jsonb 查询语言的 pg.extension。
hstore 更像是一种“宽列”存储类型,它是键值对的平面(非嵌套)字典,始终以合理有效的二进制格式存储(哈希表,因此得名)。
json 将 JSON 文档存储为文本,在存储文档时执行验证,并在需要时在输出上解析它们(即访问单个字段);它应该支持整个 JSON 规范。由于存储了整个 JSON 文本,因此保留了其格式。
jsonb 出于性能原因采用快捷方式:JSON 数据在输入时解析并以二进制格式存储,不维护字典中的键顺序,也不保留重复键。访问 JSONB 字段中的单个元素很快,因为它不需要一直解析 JSON 文本。在输出时,JSON 数据被重建并且初始格式丢失。
IMO,如果您正在处理机器可读的数据,那么一旦 jsonb
可用,不 没有重要的理由使用它。
JSONB 是 JSON 的“更好”版本。
让我们看一个例子:
SELECT '{"c":0, "a":2,"a":1}'::json, '{"c":0, "a":2,"a":1}'::jsonb;
json | jsonb
------------------------+---------------------
{"c":0, "a":2,"a":1} | {"a": 1, "c": 0}
(1 row)
JSON 存储空格,这就是为什么我们可以在存储键“a”时看到空格,而 JSONB 没有。 JSON 存储键的所有值。这就是您可以针对键 "a" 看到多个值(2 和 1)的原因,而 JSONB 仅“存储”最后一个值。 JSON 维护插入元素的顺序,而 JSONB 维护“排序”顺序。 JSONB 对象存储为解压缩的二进制文件,而不是 JSON 中的“原始数据”,在检索期间不需要重新解析数据。 JSONB 还支持索引,这是一个显着的优势。
一般来说,人们应该更喜欢 JSONB,除非有特殊需求,例如关于对象键排序的遗留假设。
关于json
和jsonb
数据类型的区别,值得一提的是官方的解释:
PostgreSQL 提供了两种存储 JSON 数据的类型:json 和 jsonb。为了对这些数据类型实现高效的查询机制,PostgreSQL 还提供了第 8.14.6 节中描述的 jsonpath 数据类型。 json 和 jsonb 数据类型接受几乎相同的值集作为输入。主要的实际区别是效率之一。 json 数据类型存储输入文本的精确副本,处理函数必须在每次执行时重新解析;而 jsonb 数据以分解的二进制格式存储,由于增加了转换开销,因此输入速度稍慢,但处理速度明显加快,因为不需要重新解析。 jsonb 还支持索引,这是一个显着的优势。因为 json 类型存储了输入文本的精确副本,所以它将保留标记之间的语义无关紧要的空白,以及 JSON 对象中键的顺序。此外,如果值中的 JSON 对象多次包含相同的键,则保留所有键/值对。 (处理函数将最后一个值视为有效值。)相比之下,jsonb 不保留空格,不保留对象键的顺序,也不保留重复的对象键。如果在输入中指定了重复键,则仅保留最后一个值。一般来说,大多数应用程序应该更喜欢将 JSON 数据存储为 jsonb,除非有非常特殊的需求,例如关于对象键排序的遗留假设。 PostgreSQL 只允许每个数据库使用一种字符集编码。因此,除非数据库编码是 UTF8,否则 JSON 类型不可能严格遵守 JSON 规范。尝试直接包含无法在数据库编码中表示的字符将失败;相反,可以在数据库编码中表示但不能在 UTF8 中表示的字符将被允许。
来源:https://www.postgresql.org/docs/current/datatype-json.html
我今天在 PostgresOpen,基准测试比 MongoDB 快得多。我相信选择的速度快了大约 500%。几乎所有东西都更快,与 MongoDB 相比至少快了 200%。然后现在的一个例外是需要完全重写整个 JSON 列的更新 - MongoDB 处理得更好。
JSONB 上的 gin 索引听起来很棒。
此外,PostgreSQL 将在内部保留 JSONB 类型,并且基本上将其与数字、文本、布尔值等类型匹配。
也可以使用 JSONB 进行连接。
为存储过程添加 PLv8,这对于 Node.js 开发人员来说基本上是梦想成真。
由于它以二进制形式存储,JSONB 还将去除所有空白,更改属性的顺序并使用属性的最后一次出现来删除重复的属性。
除了查询 JSONB 列与 JSON 列对比时的索引之外,PostgreSQL 不必实际运行将每一行上的文本转换为 JSON 的功能,这可能会单独节省大量时间。
上面任何答案中都没有提到的另一个重要区别是,json
类型没有相等运算符,但 jsonb
有一个相等运算符。
这意味着在从表中选择此 json
类型和/或其他字段时,您不能使用 DISTINCT
关键字(您可以改用 DISTINCT ON
,但由于 this 之类的情况并非总是可行) .
据我所知,
当前存在的 hstore(在 PostgreSQL 9.3 中)不允许嵌套其他对象和数组作为其键/值对的值。但是,未来的 hstore 补丁将允许嵌套。此补丁不会出现在 9.4 版本中,并且可能不会很快包含在内。
当前存在的 json 确实允许嵌套,但它是基于文本的并且不允许索引,因此它“慢”
9.4发布的jsonb会有json目前的嵌套能力,还有hstore的GIN/GIST索引,所以会很快
使用 PostgreSQL 9.4 的人似乎在说,新的、快速的 jsonb 类型会吸引那些选择使用像 MongoDB 这样的 NoSQL 数据存储的人,但它现在可以将关系数据库与可查询的非结构化数据库结合起来同一屋檐下的数据
Why HStore2/jsonb is the most important patch of 9.4
PostgreSQL 9.4 jsonb 的基准测试似乎与 MongoDB 相当,或者在某些情况下比 MongoDB 更快。
http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb
jsonb
不支持这个?UPDATE test SET data->'a' = 123 WHERE id = 1;
来自CREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
json
而不是jsonb
的原因之一是,如果由于遗留原因,您使用json
的代码依赖于json
字段的顺序并且无法重新排序。text
与json
:后者带有 JSON 验证,因此对于无效的 JSON,它只会在插入时失败,而不是每次您的应用程序读取它时都会失败(因为它获得了无效的表示)。此外,您可以安全地将后者强制转换为数据库中的jsonb
。