PostgreSQL 刚在 9.4 版本中引入了 JSONB,而且已经成为 Hacker News 上的热门话题。它与之前在 PostgreSQL 中存在的 Hstore 和 JSON 有何不同?
JSONB 有哪些优势和限制?什么时候应该考虑使用它?
PostgreSQL 刚在 9.4 版本中引入了 JSONB,而且已经成为 Hacker News 上的热门话题。它与之前在 PostgreSQL 中存在的 Hstore 和 JSON 有何不同?
JSONB 有哪些优势和限制?什么时候应该考虑使用它?
首先,hstore
是一个贡献模块,仅允许您存储键=>值对,其中键和值只能是 text
类型(但值也可以是 sql 的 NULL
)。
json
和 jsonb
都允许您存储有效的 JSON 值(在其规范中定义)。
例如,以下是有效的 JSON 表示形式:null
, true
, [1,false,"string",{"foo":"bar"}]
, {"foo":"bar","baz":[null]}
- 与 JSON 相比,hstore
只是一个小子集(但如果您只需要此子集,则没问题)。
json
和 jsonb
之间唯一的区别是它们的存储方式:
json
存储在其纯文本格式中,而jsonb
存储在某些二进制表示中这有三个主要的后果:
jsonb
通常需要比 json
更多的磁盘空间来存储(有时候不需要)jsonb
从其输入表示构建所需的时间比 json
更长json
操作所需的时间比 jsonb
还要明显地更长(并且每次在 json
类型值上执行某些操作时都需要进行解析)当 jsonb
在稳定版本中可用时,将有两个主要用例可以轻松选择它们之间的区别:
json
。jsonb
。jsonb
不支持这个呢?从 CREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
到 UPDATE test SET data->'a' = 123 WHERE id = 1;
。 - Kokizzujson
而不是 jsonb
的原因之一是,如果由于遗留问题,消费你的 json
数据的代码依赖于 json
字段的顺序,而这些字段无法重新排序。 - djdrzzyjsonb
。 - pozsPeeyush:
简短回答:
更详细的回答,请等待我在接近 9.4 发布时进行完整的“如何”撰写。
JSON和JSONB之间的区别简单解释(原始图像由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)
更多信息请参见演讲视频和幻灯片展示,由jsonb开发人员介绍。此外,他们还推出了JsQuery,一种提供强大的jsonb查询语言的pg扩展。
hstore
是一种“宽列”存储类型,它是一个扁平(非嵌套)的键值对字典,始终以合理高效的二进制格式存储(哈希表,因此得名)。json
将JSON文档存储为文本,并在存储文档时执行验证,在需要时解析它们(即访问单个字段)。它应支持整个JSON规范。由于整个JSON文本被存储,所以其格式被保留。jsonb
为了性能而采取了捷径:输入时解析JSON数据并以二进制格式存储,字典中的键排序不会维护,重复的键也不会维护。访问JSONB字段中的单个元素很快,因为它不需要一直解析JSON文本。输出时,JSON数据被重构,初始格式丢失。在处理机器可读数据时,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)
一般来说,除非有关于对象键排序的传统假设等特殊需求,否则应该优先选择 JSONB。
json
和jsonb
数据类型之间的区别,值得一提的是官方解释:json
和jsonb
。为了实现这些数据类型的高效查询机制,PostgreSQL还提供了在第8.14.6节中描述的jsonpath数据类型。
json
和jsonb
数据类型接受几乎相同的输入值集合。主要的实际差异在于效率。json
数据类型存储输入文本的精确副本,处理函数必须在每次执行时重新解析;而jsonb
数据以分解的二进制格式存储,由于没有重新解析,因此输入略慢,但处理速度显着快。jsonb
还支持索引,这可能是一个重要的优势。json
类型存储输入文本的精确副本,因此它将保留标记之间的语义上不重要的空格以及JSON对象内键的顺序。此外,如果值内的JSON对象包含多个相同的键,则保留所有键/值对。(处理函数将最后一个值视为有效值。)相反,jsonb
不保留空格,不保留对象键的顺序,并且不保留重复的对象键。如果输入中指定了重复键,则仅保留最后一个值。jsonb
,除非有相当专业的需要,例如关于对象键排序的遗留假设。我今天参加了PostgresOpen,基准测试比MongoDB快多了。对于selects查询,速度大约快了500%,几乎所有操作都比MongoDB快,至少快了200%。目前唯一的例外是更新操作需要完全重写整个JSON列 - 这是MongoDB处理得更好。
JSONB上的gin索引听起来很棒。
此外,PostgreSQL将在内部持久化JSONB类型,并基本上与数字、文本、布尔等类型匹配。
使用JSONB也可以进行联接操作。
添加PLv8作为存储过程,这对于Node.js开发人员来说基本上是梦想成真。
由于JSONB存储为二进制,它还会剥离所有空格,更改属性顺序并删除重复属性(使用属性的最后一次出现)。
除了在针对JSON列进行查询时的索引外,PostgreSQL无需在每行上运行将文本转换为JSON的功能,这可能单独节省大量时间。
还有一个重要的区别,之前没有任何答案提到过,就是 json
类型没有等于运算符,但 jsonb
有。
这意味着当从表中选择此 json
类型和/或其他字段时,您不能使用DISTINCT
关键字(您可以使用 DISTINCT ON
,但由于像此类情况而不总是可能)。
目前(在PostgreSQL 9.3中)的hstore不允许将其他对象和数组嵌套作为其键/值对的值。然而,未来的hstore补丁将允许嵌套。该补丁不会在9.4版本中发布,并且可能不会很快被包含。
json允许嵌套,但它是基于文本的,并且不允许索引,因此速度较慢。
即将在9.4中发布的jsonb将具有json的当前嵌套功能,以及hstore的GIN/GIST索引,因此速度较快。
正在开发PostgreSQL 9.4的人似乎在说,新的、快速的jsonb类型将吸引那些本来会选择使用NoSQL数据存储(如MongoDB)的人,但现在可以将关系型数据库和可查询的非结构化数据合并到一个平台上。
对于PostgreSQL 9.4 jsonb的基准测试似乎与MongoDB相当,甚至在某些情况下更快。
http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb