假设您想在您的对象(例如帖子)上存储“标签”。在 9.4 版中,您有 3 个主要选择:
- 标记为文本[]
- 标签为 jsonb
- 标记为文本(并且您将 JSON 字符串存储为文本)
在许多情况下,第 3 个是毫无疑问的,因为它不允许以“标签”值为条件的查询。在我目前的开发中,我不需要这样的查询,标签只显示在帖子列表中,而不是过滤帖子。
因此,选择主要在text[]
和之间jsonb
。两者都可以查询。
你会用什么?为什么?
假设您想在您的对象(例如帖子)上存储“标签”。在 9.4 版中,您有 3 个主要选择:
在许多情况下,第 3 个是毫无疑问的,因为它不允许以“标签”值为条件的查询。在我目前的开发中,我不需要这样的查询,标签只显示在帖子列表中,而不是过滤帖子。
因此,选择主要在text[]
和之间jsonb
。两者都可以查询。
你会用什么?为什么?
在大多数情况下,我会使用一个规范化的模式和一个option_tag
实现表之间的多对多关系的表option
和tag
. 参考实现在这里:
它可能不是所有方面最快的选项,但它提供了完整的数据库功能,包括引用完整性、约束、所有数据类型、所有索引选项和廉价更新。
为了完整起见,请添加到您的选项列表中:
hstore
(不错的选择)xml
hstore
比or更冗长和复杂jsonb
,所以我只会在使用 XML 操作时使用它。如果列表只是为了显示并且很少更新,我会考虑一个普通的数组,它通常更小并且比其他的表现更好。
阅读Josh Berkus @a_horse 在他的评论中链接到的博客条目。但请注意,它侧重于选定的读取案例。乔什承认:
我意识到我没有测试比较写入速度。
这就是规范化方法大获全胜的地方,尤其是当您在并发负载下大量更改单个标签时。
jsonb
无论如何,如果您要使用 JSON 进行操作,并且可以“按原样”存储和检索 JSON,这只是一个不错的选择。
我既使用了规范化模式,也使用了text
带有 CSV 分隔值的普通字段,而不是自定义数据类型(除了 CSV,您可以使用 JSON 或任何其他编码,如 www-urlencoding 甚至 XML 属性编码)。这是因为许多 ORM 和数据库库不太擅长支持自定义数据类型(hstore、jsonb、数组等)。
@ErwinBrandstetter 错过了规范化的其他几个好处,即在规范化模式中查询所有可能以前使用的标签比数组选项要快得多。这是许多标签系统中非常常见的场景。
话虽如此,我建议使用 Solr(或 elasticsearch)来查询标签,因为它处理标签计数和一般标签前缀搜索比我可以让 Postgres 做的要好得多,如果你愿意处理与同步的一致性方面搜索引擎。因此,标签的存储变得不那么重要了。