PostgreSQL引入的JSONB解释

时间:2014-03-26 07:26:43

标签: json postgresql nosql postgresql-json jsonb

PostgreSQL刚刚介绍了JSONB,它已经在hacker news上发展趋势。如果有人能够解释它与之前在PostgreSQL中出现的Hstore和JSON有什么不同,那将会很棒。它的优点和局限是什么?何时有人考虑使用它?

9 个答案:

答案 0 :(得分:390)

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

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

F.ex。这些是有效的JSON表示:nulltrue[1,false,"string",{"foo":"bar"}]{"foo":"bar","baz":[null]} - hstore只是JSON能力的一小部分(但如果你只需要这个子集,没关系。

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

  • json以纯文本格式存储,而
  • jsonb存储在某个二进制表示

这有三个主要后果:

  • jsonb通常需要更多的磁盘空间来存储,而不是json(有时不会)
  • jsonb需要更多时间来构建输入表示而不是json
  • json操作显着的时间超过jsonb(并且每次在json类型值执行某些操作时也需要进行解析)

jsonb可用于稳定版本时,会有两个主要用例,您可以轻松地在它们之间进行选择:

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

答案 1 :(得分:109)

Peeyush:

简短的回答是:

  • 如果您在 PostgreSQL中进行了大量的JSON操作,例如排序,切片,拼接等,您应该出于速度原因使用JSONB。
  • 如果您需要对JSON上的任意键搜索进行索引查找,那么您应该使用JSONB。
  • 如果您没有采用上述两种方法,则应该使用JSON。
  • 如果您需要保留密钥排序,空格和重复密钥,则应使用JSON。

要获得更长的答案,您需要等待我做一个完整的" HowTo"写作更接近9.4版本。

答案 2 :(得分:53)

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 videoslide show presentation中的详细信息。他们还介绍了 JsQuery ,pg.extension提供了强大的jsonb查询语言

答案 3 :(得分:48)

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

IMO,如果您正在使用机器可读数据,那么使用jsonb后没有明显的理由。

答案 4 :(得分:14)

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

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

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

由于json类型存储输入文本的精确副本,因此它将 保留标记之间语义上无关紧要的空白,例如 以及JSON对象中键的顺序。另外,如果是JSON对象 值中包含多次相同的键,所有 键/值对被保留。 (处理功能考虑到最后 值作为执行值。)相反,jsonb不会保留 空白,不保留对象键的顺序,并且不 保留重复的对象键。如果在 输入,仅保留最后一个值。

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

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

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

答案 5 :(得分:12)

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

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

此外,postgres将在内部持久保存jsonb类型,并基本上将其与数字,文本,布尔等类型匹配。

使用jsonb

也可以加入

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

将它存储为二进制jsonb也将删除所有空格,更改属性的顺序并使用属性的最后一次出现删除重复属性。

除了查询与json列对比的jsonb列时的索引postgres不必实际运行将文本转换为每行上的json的功能,这可能会节省大量时间。

答案 6 :(得分: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相当或在某些情况下更快

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

答案 7 :(得分:6)

jsonb"更好" JSON的版本。让我们看一个例子的帮助。

Comparison by Professional Postgres

  1. JSON存储空白区域,这就是为什么我们可以在键和#34; a"存储,而JSONB不存储。
  2. JSON存储密钥的所有值。这就是你可以看到多个值(2和1)与键#34; a" ,而只有JSONB"商店"最后一个值。
  3. JSON维护元素被插入的顺序,而JSONB维护"排序"顺序。
  4. JSONB对象存储为解压缩二进制文件,而不是"原始数据"在JSON中,在检索期间不需要重新分析数据。
  5. JSONB还支持索引,这可能是一个显着的优势。
  6. 通常,人们应该更喜欢JSONB,除非有非常特殊的需求,例如关于对象键排序的遗留假设。

答案 8 :(得分:1)

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

这意味着,当您从表格中选择此DISTINCT - 类型和/或其他字段时,您无法使用json关键字(您可以使用DISTINCT ON代替$a = 0 function func(){ global $a; for ($i = 0; $i < 10; $i++){ $a += 1 } var_dump($a) } func() var_dump($a) 由于像this)这样的情况,并不总是可能的。