JSONB 会使 PostgreSQL 数组变得无用吗?
Does JSONB make PostgreSQL arrays useless?
假设你想在你的对象上存储 "tags"(比如 post)。对于 9.4 版,您有 3 个主要选择:
- 标记为文本[]
- 标记为 jsonb
- 标签作为文本(并且您将 JSON 字符串存储为文本)
在许多情况下,3rd 是不可能的,因为它不允许以 'tags' 值为条件的查询。在我目前的开发中,我不需要这样的查询,标签只显示在 posts 列表中,而不是过滤 posts.
因此,选择主要在 text[]
和 jsonb
之间。两者都可以查询。
你会用什么?为什么?
在大多数情况下,我会使用 normalized schema 和 table option_tag
实现 table 和 option
之间的多对多关系和 tag
。此处参考实现:
- How to implement a many-to-many relationship in PostgreSQL?
它可能不是各方面最快的选择,但它提供了完整的数据库功能,包括参照完整性、约束、完整的数据类型、所有索引选项和廉价更新。
为了完整起见,请添加到您的选项列表中:
hstore
(不错的选择)
xml
比 hstore
或 jsonb
更冗长和更复杂,所以我只会在使用 XML. 操作时使用它
- "string of comma-separated values"(非常简单,主要是错误的选择)
- EAV(实体-属性-值)或"name-value pairs"(主要是错误的选项)
dba.SE 这个相关问题下的详细信息:
如果列表仅用于显示且很少更新,我会考虑一个普通数组,它通常比其他数组更小且性能更好。
阅读他的评论中链接到的 blog entry by Josh Berkus @a_horse。但请注意,它侧重于选定的阅读案例。乔希承认:
I realize that I did not test comparative write speeds.
这就是规范化方法大获全胜的地方,尤其是当您在并发负载下大量更改单个标签时。
jsonb
只是一个不错的选择,如果你无论如何都要用 JSON 操作,并且可以存储和检索 JSON "as is".
我同时使用了规范化架构和仅使用 CSV 分隔值而不是自定义数据类型的普通 text
字段(您可以使用 JSON 或任何其他编码,例如 www- urlencoding 甚至 XML 属性编码)。这是因为许多 ORM 和数据库库不太擅长支持自定义数据类型(hstore、jsonb、array 等)。
@ErwinBrandstetter 错过了规范化的其他几个好处,即与数组选项相比,在规范化模式中查询所有可能的先前使用的标签要快得多。这是很多标签系统中很常见的场景。
话虽如此,我还是建议使用 Solr(或 elasticsearch)来查询标签,因为它处理标签计数和一般标签前缀搜索的方式比我让 Postgres 做的要好得多(如果您愿意处理一致性)与搜索引擎同步的各个方面。因此标签的存储变得不那么重要了。
假设你想在你的对象上存储 "tags"(比如 post)。对于 9.4 版,您有 3 个主要选择:
- 标记为文本[]
- 标记为 jsonb
- 标签作为文本(并且您将 JSON 字符串存储为文本)
在许多情况下,3rd 是不可能的,因为它不允许以 'tags' 值为条件的查询。在我目前的开发中,我不需要这样的查询,标签只显示在 posts 列表中,而不是过滤 posts.
因此,选择主要在 text[]
和 jsonb
之间。两者都可以查询。
你会用什么?为什么?
在大多数情况下,我会使用 normalized schema 和 table option_tag
实现 table 和 option
之间的多对多关系和 tag
。此处参考实现:
- How to implement a many-to-many relationship in PostgreSQL?
它可能不是各方面最快的选择,但它提供了完整的数据库功能,包括参照完整性、约束、完整的数据类型、所有索引选项和廉价更新。
为了完整起见,请添加到您的选项列表中:
hstore
(不错的选择)xml
比hstore
或jsonb
更冗长和更复杂,所以我只会在使用 XML. 操作时使用它
- "string of comma-separated values"(非常简单,主要是错误的选择)
- EAV(实体-属性-值)或"name-value pairs"(主要是错误的选项)
dba.SE 这个相关问题下的详细信息:
如果列表仅用于显示且很少更新,我会考虑一个普通数组,它通常比其他数组更小且性能更好。
阅读他的评论中链接到的 blog entry by Josh Berkus @a_horse。但请注意,它侧重于选定的阅读案例。乔希承认:
I realize that I did not test comparative write speeds.
这就是规范化方法大获全胜的地方,尤其是当您在并发负载下大量更改单个标签时。
jsonb
只是一个不错的选择,如果你无论如何都要用 JSON 操作,并且可以存储和检索 JSON "as is".
我同时使用了规范化架构和仅使用 CSV 分隔值而不是自定义数据类型的普通 text
字段(您可以使用 JSON 或任何其他编码,例如 www- urlencoding 甚至 XML 属性编码)。这是因为许多 ORM 和数据库库不太擅长支持自定义数据类型(hstore、jsonb、array 等)。
@ErwinBrandstetter 错过了规范化的其他几个好处,即与数组选项相比,在规范化模式中查询所有可能的先前使用的标签要快得多。这是很多标签系统中很常见的场景。
话虽如此,我还是建议使用 Solr(或 elasticsearch)来查询标签,因为它处理标签计数和一般标签前缀搜索的方式比我让 Postgres 做的要好得多(如果您愿意处理一致性)与搜索引擎同步的各个方面。因此标签的存储变得不那么重要了。