PostgreSQL引入的JSONB解释


345

PostgreSQL刚刚引入了JSONB,并且它已经在黑客新闻中流行。如果有人能够解释它与以前在PostgreSQL中存在的Hstore和JSON有何不同,那将是很棒的。它的优点和局限性是什么?何时应该考虑使用它?


4
从PGCon2014:youtube.com/...
msanford

5
@CraigRinger的网址不够精确,现在,一年后,它甚至还不够接近与JSONB相关的内容。
berkus

2
@berkus我以为我已链接到特定帖子。真令人沮丧
Craig Ringer 2015年

1
它确实指向特定的视频。
talonx

Answers:


455

首先,hstore是一个contrib模块,它仅允许您存储key => value对,其中key和value只能是texts(但是值也可以是sql NULLs)。

两者json&都jsonb允许您存储有效的JSON (在其spec中定义)。

F.ex. 这些都是有效的JSON表示:nulltrue[1,false,"string",{"foo":"bar"}]{"foo":"bar","baz":[null]}- hstore相比有什么JSON能够只是一个小的子集(但如果你只需要这个子集,它的罚款)。

json&之间的唯一区别jsonb是它们的存储:

  • json 以其纯文本格式存储,而
  • jsonb 以某种二进制表示形式存储

这有3个主要结果:

  • jsonb通常要花费比json(有时不是)更多的磁盘空间来存储
  • jsonb 从其输入表示构建所需的时间比 json
  • json操作采取显著的时间比jsonb(也分析必须在每一个你做一些工作时间进行json类型化值)

jsonb将有稳定版本发布时,将有两个主要用例,您可以在它们之间轻松选择:

  1. 如果仅在应用程序中使用JSON表示形式,则PostgreSQL仅用于存储和检索此表示形式,应使用json
  2. 如果您在PostgreSQL中对JSON值进行了大量操作,或对某些JSON字段使用索引,则应使用jsonb

1
嗨,由于它具有二进制表示形式,为什么jsonb不支持它呢?UPDATE test SET data->'a' = 123 WHERE id = 1;CREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu 2014年

1
Kokizzu,可能在9.5中。wiki.postgresql.org/wiki/…–
ChelowekKot

1
我想补充,你也可能使用的原因之一json以上jsonb是如果遗留原因代码消耗的json依赖于的排序json字段,它们不能被重新排序。
djdrzzy

4
因为,出于遗留原因:在JSON中,如果对象的(键,表,映射,哈希,无论在宿主语言中称为什么)键值对的排序不同,则在语义上没有任何区别。如果您依赖于此,则实际上是在使用与JSON不同的东西。-对于textvs json:后者带有JSON验证,因此,在无效JSON时,它只会在插入时失败,而不是在您的应用程序每次读取它时都会失败(因为它得到了无效的表示)。同样,您可以安全地将后者转换jsonb为数据库中的内容。
pozs

2
这是解释实施细节JSONB(大后pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html
manugupt1

131

Peeyush:

简短的答案是:

  • 如果您要进行大量JSON操作 PostgreSQL,例如排序,切片,拼接等,出于速度原因,应该使用JSONB。
  • 如果您需要索引查找以在JSON上进行任意键搜索,则应使用JSONB。
  • 如果您以上都不做,则可能应该使用JSON。
  • 如果需要保留键顺序,空格和重复键,则应使用JSON。

要获得更长的答案,您需要等待我完成接近9.4版本的完整“ HowTo”撰写。


74

一个简单的解释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)
  • json:文本存储“按原样”
  • jsonb:无空格
  • jsonb:没有重复的密钥,最后一个密钥获胜
  • jsonb:按键已排序

更多有关jsonb开发人员的演讲视频幻灯片演示。他们还引入了JsQuery,pg.extension提供了强大的jsonb查询语言


1
谢谢,我已将其替换为文本
ChelowekKot 2015年

55
  • hstore 更像是“宽列”存储类型,它是键-值对的平面(非嵌套)字典,始终以合理有效的二进制格式(哈希表,因此是名称)存储。
  • json将JSON文档存储为文本,在存储文档时执行验证,并在需要时在输出中解析它们(即访问单个字段);它应该支持整个JSON规范。由于存储了整个JSON文本,因此将保留其格式。
  • jsonb出于性能原因而采取捷径:JSON数据在输入时进行解析,并以二进制格式存储,字典中的键顺序不予维护,也不是重复的键。访问JSONB字段中的单个元素很快,因为它不需要一直解析JSON文本。在输出时,将重建JSON数据,并且会丢失初始格式。

IMO,如果您使用的是机器可读数据,则没有重要的理由使用jsonb它。


24

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)
  1. JSON存储空格,这就是为什么当存储键“ a”时我们可以看到空格,而JSONB不存储空格。
  2. JSON存储key的所有值。这就是为什么您可以在键“ a”上看到多个值(2和1),而JSONB仅“存储”最后一个值的原因。
  3. JSON保持插入元素的顺序,而JSONB保持“排序”顺序。
  4. JSONB对象以解压缩的二进制形式存储,而不是JSON中的“原始数据”,在JSON检索过程中不需要重新解析数据。
  5. JSONB还支持索引编制,这是一个很大的优势。

通常,除非有特殊需要,例如关于对象键顺序的传统假设,否则应该首选JSONB。


13

我今天在pgopen上,基准测试速度比mongodb快得多,我相信选择速度要快500%。与mongodb相比,几乎所有东西都至少快了200%,而现在的一个例外是更新,它需要完全重写整个json列,而mongodb处理得更好。

jsonb上的杜松子酒索引听起来很棒。

而且postgres会在内部保留jsonb类型,并且基本上将其与数字,文本,布尔值等类型匹配。

也可以使用jsonb加入

为存储过程添加PLv8,对于node.js开发人员来说,这基本上是梦想成真。

由于它以二进制jsonb的形式存储,因此也会删除所有空白,更改属性的顺序,并使用属性的最后一次出现删除重复的属性。

除了在查询与json列相反的jsonb列时使用索引之外,postgres不必实际运行将文本转换为json的功能,这可能会节省大量的时间。


7

关于jsonjsonb数据类型之间的区别,值得一提的是官方解释:

PostgreSQL提供两种存储JSON数据的类型:jsonjsonb。为了对这些数据类型实现有效的查询机制,PostgreSQL还提供了8.14.6 节中描述的jsonpath数据类型。

jsonjsonb数据类型接受值作为输入的几乎相同的集。实际的主要区别是效率之一。该 json数据类型存储所输入的文本,该文本处理功能必须在每次执行时重新分析的精确副本; 而jsonb数据被存储在一个分解的二进制格式,使得它稍微慢于输入由于添加转换开销,但显著更快的过程,因为不需要重新解析。jsonb还支持索引编制,这可能是一个很大的优势。

因为json类型存储了输入文本的精确副本,所以它将保留标记之间语义上无关紧要的空白以及JSON对象中键的顺序。此外,如果值中的JSON对象包含相同的键不止一次,则所有键/值对都会保留。(处理功能将最后一个值视为可操作值。)相比之下,jsonb不保留空格,不保留对象键的顺序,也不保留重复的对象键。如果在输入中指定了重复的键,则仅保留最后一个值。

通常,大多数应用程序应该将JSON数据存储为 jsonb,除非有非常特殊的需求,例如关于对象键顺序的传统假设。

PostgreSQL每个数据库只允许一种字符集编码。因此,除非数据库编码为UTF8,否则JSON类型不可能严格符合JSON规范。尝试直接包含数据库编码中无法表示的字符将失败;相反,将允许使用可以在数据库编码中表示但不能以UTF8表示的字符。

来源:https : //www.postgresql.org/docs/current/datatype-json.html


6

据我所知,

  • 当前存在的hstore(在PostgreSQL 9.3中)不允许嵌套其他对象和数组作为其键/值对的值。但是,将来的hstore修补程序将允许嵌套。此修补程序将不在9.4版本中,并且可能很快将不包含在内。

  • JSON,因为它目前存在确实允许嵌套,但基于文本的,并且不允许索引,因此它是“慢”

  • 随9.4版本一起发布的jsonb将具有json的当前嵌套功能,以及hstore的GIN / GIST索引,因此速度很快

使用PostgreSQL 9.4的人们似乎在说,新的快速jsonb类型将吸引那些选择使用像MongoDB这样的noSQL数据存储的人,但是现在可以将关系数据库与可查询的非结构化数据结合在一起

http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html

Postgresql 9.4 jsonb的基准似乎与MongoDB相当或在某些情况下比MongoDB更快

http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb


6

上面的任何答案中都没有提到的另一个重要区别是,json类型没有相等运算符,而类型有一个相等运算符jsonb

这意味着您不能DISTINCTjson从表中选择此-type和/或其他字段时使用关键字(您可以改用DISTINCT ON它,但由于这种情况,并非总是可能的)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.