【问题标题】:Explanation of JSONB introduced by PostgreSQLPostgreSQL引入JSONB的解释
【发布时间】:2014-05-04 10:51:15
【问题描述】:

PostgreSQL 刚刚介绍了JSONB,它已经成为趋势on hacker news。它与以前在 PostgreSQL 中存在的 Hstore 和 JSON 有什么不同?

它有什么优点和局限性,什么时候应该考虑使用它?

【问题讨论】:

  • 来自 PGCon2014:youtube.com/…
  • @CraigRinger 网址不够精确,现在,1 年后,它甚至没有足够接近 JSONB 相关内容。
  • @berkus 我以为我链接到了具体的帖子。多么令人沮丧。
  • 它确实指向特定的视频。

标签: json postgresql nosql postgresql-json jsonb


【解决方案1】:

关于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

【讨论】:

    【解决方案2】:

    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 存储键的所有值。这就是您可以针对键 "a" 看到多个值(2 和 1)的原因,而 JSONB 仅“存储”最后一个值。
    3. JSON 维护插入元素的顺序,而 JSONB 维护“排序”顺序。
    4. JSONB 对象存储为解压缩的二进制文件,而不是 JSON 中的“原始数据”,在检索期间不需要重新解析数据。
    5. JSONB 还支持索引,这是一个显着的优势。

    一般来说,人们应该更喜欢 JSONB,除非有特殊需求,例如关于对象键排序的遗留假设。

    【讨论】:

      【解决方案3】:

      简单解释一下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,一个提供强大 jsonb 查询语言的 pg.extension。

      【讨论】:

      • 谢谢,我已经换成文字了
      【解决方案4】:

      我今天在PostgresOpen,基准测试比MongoDB 快得多。我相信选择的速度快了大约 500%。几乎所有东西都更快,与 MongoDB 相比至少快了 200%。然后现在的一个例外是需要完全重写整个 JSON 列的更新 - MongoDB 处理得更好。

      JSONB 上的 gin 索引听起来很棒。

      PostgreSQL 还将在内部保留 JSONB 类型,并且基本上将其与数字、文本、布尔值等类型匹配。

      也可以使用 JSONB 进行连接。

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

      由于它是以二进制形式存储的,JSONB 还将去除所有空白,更改属性的顺序并使用属性的最后一次出现来删除重复的属性。

      除了查询 JSONB 列而不是 JSON 列时的索引之外,PostgreSQL 不必实际运行将每一行上的文本转换为 JSON 的功能,这可能会单独节省大量时间。

      【讨论】:

        【解决方案5】:

        据我所知,

        • 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

        【讨论】:

        • 最后一个链接坏了:"DisallowedHost at /alphabetum/postgresql-incl-hstore-vs-mongodb"
        【解决方案6】:

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

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

        【讨论】:

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

          IMO,如果您正在处理机器可读的数据,那么使用jsonb 并没有什么重要的原因。

          【讨论】:

            【解决方案8】:

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

            jsonjsonb 都允许您存储有效的 JSON (在其 spec 中定义)。

            F.ex.这些是有效的 JSON 表示形式:nulltrue[1,false,"string",{"foo":"bar"}]{"foo":"bar","baz":[null]} - hstore 与 JSON 的能力相比只是一个小子集(但如果你只需要这个子集,那很好)。

            jsonjsonb 之间的唯一区别是它们的存储:

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

            这样做有 3 个主要后果:

            • jsonb 通常需要比json 更多的磁盘空间来存储(有时不会)
            • jsonbjson 需要更多时间从其输入表示中构建
            • json 操作比jsonb 花费显着更多的时间(每次您在json 键入的值处执行某些操作时,也需要进行解析)

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

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

            【讨论】:

            • 嗨,既然它有二进制表示,为什么jsonb 不支持这个? UPDATE test SET data->'a' = 123 WHERE id = 1; 来自CREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
            • Kokizzu,在 9.5 中可以。 wiki.postgresql.org/wiki/…
            • 只是补充一点,您可能还使用json 而不是jsonb 的原因之一是,如果由于遗留原因,您的代码使用您的json 取决于json 字段的顺序而且它们不能重新排序。
            • 由于遗留原因:在 JSON 中,如果一个对象的(表、映射、哈希,无论它在宿主语言中调用什么)键值对的顺序不同,则没有语义差异.如果您依赖它,那么您实际上使用的是与 JSON 不同的东西。 -- 对于textjson:后者带有 JSON 验证,因此在无效 JSON 时,它只会在插入时失败,而不是每次应用程序读取它时都会失败(因为它得到一个无效的表示)。此外,您可以安全地将后者转换为数据库中的jsonb
            • 这篇文章很好地解释了 JSONB 的实现细节 (pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html)
            【解决方案9】:

            佩尤什:

            简短的回答是:

            • 如果您在内部 PostgreSQL 中进行大量 JSON 操作,例如排序、切片、拼接等,出于速度原因,您应该使用 JSONB。
            • 如果您需要对 JSON 上的任意键搜索进行索引查找,那么您应该使用 JSONB。
            • 如果您不执行上述任何一项操作,您可能应该使用 JSON。
            • 如果您需要保留键顺序、空格和重复键,则应使用 JSON。

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-09-11
              • 1970-01-01
              • 2019-10-02
              • 2020-12-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2023-03-13
              相关资源
              最近更新 更多