PostgreSQL 刚刚引入了JSONB,它已经成为黑客新闻的热门话题。它与以前存在于 PostgreSQL 中的 Hstore 和 JSON 有何不同?
它的优点和局限性是什么?什么时候应该考虑使用它?
首先,hstore
是一个 contrib 模块,它只允许您存储 key => value 对,其中键和值只能是text
s(但是值也可以是 sql NULL
)。
json
&都jsonb
允许您存储有效的 JSON值(在其规范中定义)。
前任 这些是有效的 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
.jsonb
.皮尤什:
简短的回答是:
要获得更长的答案,您需要等待我在接近 9.4 版本时完成完整的“HowTo”写作。
简单解释一下 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.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)
一般来说,人们应该更喜欢 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
.
这意味着您在从表中DISTINCT
选择此json
类型和/或其他字段时不能使用关键字(您可以改用,但由于这种DISTINCT ON
情况并不总是可行)。
据我所知,
当前存在的 hstore(在 PostgreSQL 9.3 中)不允许嵌套其他对象和数组作为其键/值对的值。但是,未来的 hstore 补丁将允许嵌套。此补丁不会出现在 9.4 版本中,并且可能不会很快包含在内。
当前存在的 json确实允许嵌套,但它是基于文本的并且不允许索引,因此它“慢”
9.4发布的jsonb会有json目前的嵌套能力,还有hstore的GIN/GIST索引,所以会很快
使用 PostgreSQL 9.4 的人似乎在说,新的、快速的 jsonb 类型将吸引那些选择使用像MongoDB这样的NoSQL数据存储的人,但它现在可以将关系数据库与可查询的非结构化数据结合在一个屋檐下
为什么 HStore2/jsonb 是 9.4 最重要的补丁
PostgreSQL 9.4 jsonb 的基准测试似乎与 MongoDB 相当,或者在某些情况下比 MongoDB 更快。
http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb