将数组存储为字段值或将数组值存储为记录是不是一个好主意?

时间:2016-01-25 14:25:58

标签: sql database postgresql database-design

在我的申请表中,我有#34;文章" (类似于帖子/推文/文章)标有描述性预定义标签:即"困难","简单","红","蓝& #34;," business"等

这些可用的标签存储在一个表格中,称之为"标签"包含所有可用标签。

每篇文章都可以标记多个标签,可通过自定义管理界面进行编辑。

简单地将每个实体的标签捆绑到每个标签的ID的字符串化数组中并将其与文章记录一起存储在我的"文章"中可能很诱人。表:

id | title | author | tags
---+-------+--------+-------------
1  | title | TG     | "[1,4,7,12]"

虽然由于多种原因我确定这是一个坏主意,是否有合理的理由去做上述事情?

3 个答案:

答案 0 :(得分:8)

我认为您应该阅读Database normalization并自行决定。简而言之,您的提案存在许多问题,但您可能认为可以与他们共处。

最明显的是:

  1. 如果在行(1)中添加了其他标记怎么办?您是否必须先解析,检查它是否已存在,然后将该行更新为tags.append(newTag)
  2. 更糟糕的是还在删除标签?搜索标签存在,重新创建标签。
  3. 如果标签要更改名称 - 可能是一些审核过程怎么办?
  4. 再次更糟糕的是,不同的人不同地指定标签名称 - 这很难合理化。
  5. 如果您想根据标签查询数据怎么办?您的查询变得比它需要的复杂得多。
  6. 演示文稿:客户端必须解析标记才能使用它。分隔符字段怎么样?改变这一点,所有客户都必须改变。
  7. 简而言之,所有这些操作都变得更加困难和繁琐。规范化旨在克服这些问题。做你所说的IMO的唯一原因可能就是你将数据捕获为一次性而且仅仅是信息性的 - 也就是说,对用户而不是系统本身是有意义的。这有点像说它最好避免(再次,IMO)。

答案 1 :(得分:2)

在我看来,你想拥有一个单独的表来存储标签,并拥有一个外键,它将标签记录与文章表中的父记录联系起来(这被称为"正常化&#34 ;数据库结构)。

就像你通过将标记塞进一个字段所建议的那样做现在看起来似乎有意义,但随着应用程序的大小增加或者随着应用程序的增长而有效地提取值时,它将难以维护和困难/耗时。数据量增长了很多。

我想说,根据你所建议的内容的理由很少,因为创建另一个表并建立关系以在两个表之间链接键以保持参照完整性是多么简单。

答案 2 :(得分:0)

我完全同意 CAN 是个好主意。我强烈主张将数据库中的标签存储为单个分隔的字符串列表。

但是:我同意的原因是我喜欢使用Azure Search API来索引这些类型的数据,因此基于标签进行查找的查询不是通过SQL完成的。 (使用Azure搜索API服务不是必需的,但根据我的经验,通过使用数据库之外的搜索索引,您将获得更好的性能和可伸缩性。)

  

如果您的主要查询语言是SQL(基于关系的查询)   那么你最好创建一个每个都有一行的子表   标记,否则您将在查询时遇到性能损失   对每个值执行逻辑以将其拆分以进行分析。

标记是我们用来绕过关系数据或分层映射的概念,因此要获得最佳性能,请不要尝试使用这些关系概念来查询标记。它通常最好在NoSQL数据存储中实现,因为它们不会尝试使用数据库来处理搜索查询。

我建议您将数据存储为分隔字符串,并使用外部索引服务提供对数据的搜索和洞察。这是在CRUD数据访问性能尝试管理数据和索引以优化搜索之间的良好折衷。当然,您可以优化数据库和搜索查询,使其在SQL中运行,但可能需要付出努力才能使其正确。

一旦您的用户群达到大量并且您需要支持多个并发搜索而不影响更新性能,您会发现外部索引在您现在的时间内是一项非常棒的投资,以便以后节省您的时间和资源。