【问题标题】:Is it ever a good idea to store an array as a field value, or store array values as records?将数组存储为字段值或将数组值存储为记录是个好主意吗?
【发布时间】:2016-05-01 21:38:44
【问题描述】:

在我的应用程序中,我有带有描述性预定义标签的“文章”(类似于帖子/推文/文章):即“困难”、“简单”、“红色”、“蓝色”、“业务”等等

这些可用标签存储在一个表中,称为“标签”,其中包含所有可用标签。

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

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

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

尽管出于多种原因,我确信这是一个坏主意,但是否有合理的理由来执行上述操作?

【问题讨论】:

  • 我不知道 PostgreSQL,但由于它似乎支持 XML,将标签列表存储为 XML 字符串可以比简单的分隔列表带来实质性的好处。

标签: sql database postgresql database-design


【解决方案1】:

我认为您应该阅读Database normalization 并自行决定。简而言之,您的提案存在许多问题,但您可以决定接受这些问题。

最明显的是:

  1. 如果在第 (1) 行添加了一个额外的标签怎么办?您是否必须先解析,检查它是否已经存在,然后将行更新为tags.append(newTag)。
  2. 仍然删除标签更糟糕?搜索标签,存在,重新创建标签。
  3. 如果标签要更改名称怎么办?也许需要一些审核过程?
  4. 更糟糕的是,如果不同的人以不同的方式指定标签名称会怎样 - 这很难合理化。
  5. 如果要根据标签查询数据怎么办?您的查询变得比需要的复杂得多。
  6. 演示:客户端必须解析标签才能使用它。分隔符字段呢?改变这一点,所有客户都必须改变。

简而言之,所有这些操作都变得更加困难和繁琐。规范化旨在克服这些问题。 IMO,做你所说的事情的唯一原因可能是你一次性捕获数据,而且它只是信息性的——也就是说,对用户有意义,但对系统本身没有意义。这有点像说它可能最好避免(再次,IMO)。

【讨论】:

    【解决方案2】:

    在我看来,您似乎想要一个单独的表来存储标签并保存一个外键,该外键将标签记录与文章表中的父记录相关联(这被称为“规范化”数据库结构) .

    按照您的建议将标签塞进一个字段现在似乎很有意义,但随着应用程序规模的增长或数据量增长了很多。

    考虑到创建另一个表并设置关系以链接两个表之间的键以保持引用完整性是多么简单,我想说几乎没有理由按照您的建议进行操作。

    【讨论】:

      【解决方案3】:

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

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

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

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

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

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

      【讨论】:

      • 逗号分隔的字符串肯定不是这里的方法。 PostgreSQL 中有一系列基于 GisT/GIN 的索引,可以很好地搜索整数数组或文本标记。
      • 一组整数或文本标记......它们以某种方式分隔对吗?我的观点是,无论您选择使用哪种格式,如果您的查询语言支持优化的数据访问方式,将数据存储在数据库中的单个字段中是完全有效的。所以对我来说,听起来你实际上同意 :) 我对逗号很满意,因为我选择的索引方法可以比这种单字段格式的其他结构更快地处理逗号分隔的字符串。
      • 这不是真正的讨论论坛,但不是没有分隔 - 存储为适当的结构化类型。将其全部混合成文本是最后的手段。 postgresql.org/docs/current/static/datatype.html
      • 点 :) 在我的无知中,我没有意识到这个问题是专门为 PostgreSQL 标记的
      猜你喜欢
      • 2018-11-18
      • 1970-01-01
      • 2020-09-05
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 2016-12-06
      • 2010-10-30
      • 2015-09-25
      相关资源
      最近更新 更多