【问题标题】:MYSQL and Normalisation: How to handle lots of optional fields?MYSQL 和规范化:如何处理大量可选字段?
【发布时间】:2012-04-28 21:42:05
【问题描述】:

我有一个个人资料页面,上面有大约 20 个可选字段。为了使其正常化,我必须创建 20 个不同的表,然后在其中使用 20 JOINS 进行查询。这对我来说似乎有点过头了。

这是最好的方法吗?

你建议我保持正常化吗?

【问题讨论】:

  • 一个“可选”字段只是意味着该值可以为空......不知道为什么你认为这意味着 20 个额外的表。
  • @Andy 请注意,有多种规范化形式。您可能会发现预先确定您的目标是有帮助的,并且还可以确定性能、存储空间、可维护性、适应性等的重要性。否则你只是在黑暗中拍摄。
  • 因为在一个表中有 1000 万次 null 意味着它没有标准化
  • 在任何表中即使 once 也有 null 意味着它没有被规范化。所有传统的范式都假定关系仅由其元组中的常规值组成 - 从不为空。

标签: mysql normalization


【解决方案1】:

做到这一点的一个好方法(虽然有点混乱,除非你知道发生了什么)是使用相同的设计 wordpress 使用 - 据我所知,它被称为实体属性值(感谢@Matt Fenwick)。 https://stackoverflow.com/tags/eav/info

基本的想法是,你有两张桌子,而不是你的 20 个INNER JOIN-able 桌子来存储零碎物品。一个存储您的实体(wordpress 案例中的一个帖子),第二个存储您所有的零碎物品 - 或 WP 所指的元数据。 您不必为每个数据点设置一列,而是将一列用于名称,一列用于值,一列用于该属性适用的实体的 ID。

通过这种方式,您可以节省大量 SQL、扩展过程中的麻烦以及开始构建它所需的时间。如果您需要满足另一个属性,您只需将其与其余部分一起放入其中 - 无需破解架构。

关于 WP 数据库布局的更多细节(这里我主要考虑 wp_posts 和 wp_postmeta 表):http://codex.wordpress.org/Database_Description

所以一个例子可能是(伪代码,对不起):

table: yourEntity
entityID  int, primary key, auto increment
title     varchar

table: yourEntityMeta
entityID  int, non-unique key
name      text
value     text

通过这种方式,您可以为每个实体拥有任意数量的属性,而对于具有 NULL 值的未使用列和需要连接的另外 18 个表没有任何限制或性能问题。

希望对你有帮助

注意:这里的一个问题(由 cmets 中的 @ypercube 指出)是使用这意味着您不能为每个属性指定数据类型,即日期属性将存储为文本,布尔值也是如此或诠释。您也无法使用外键链接到有效值表(感谢@Catcall)。在沿着这条路线走之前,您需要仔细考虑这一点。

【讨论】:

  • @jammypeach 所以基本上我将所有值保存在一列中,用逗号或类似的东西分隔?
  • @jammypeach:不执行 EAV 的主要原因是您失去了完整性执行。就像你的例子一样,一切都是text
  • @MattFenwick 这是 cookie,谢谢。 @Andy Lobel 不,您将为每个属性/值对使用一个新行-即 colour=blue, name=kitty, age=2 将是 3 个单独的行。如果您需要它们,您可以在它们上使用group concat 来获取列表。
  • @ypercube 是的。 OP 没有在这方面指定任何要求,但这是一个有效的观点,请参阅更新的答案。
  • @jammypeach 总是可以为 type 放置一个列,然后在 php 中进行类型转换哈哈,反正所有字段都是字符串,所以没关系
【解决方案2】:

如果选项字段是常量,请考虑使用 ENUM(用于 2-20 个选项),但是这种方法有其自身的缺陷。

如果您主要关心的是数据库规范化,那么即使您有 20 个选项字段,您也应该为每个选项字段提供单独的“查找”表,这样您就不会存储重复数据。

此外,如果您决定在将来更改选项,它会使您的表在将来更容易维护。

JOIN 语句还不错,MySQL 在一次查询中最多可以支持 61 个表。我已经在 this question of mine 中探讨过该主题。

【讨论】:

  • 有道理(我认为 enum 与 jammypeach 所说的相同)。我会把它投票给 1,但我已经从 -1 投票给它了,哈哈
【解决方案3】:

我只会对可选字段使用可为空的列。该表会变得很大,但是如此多的连接只会降低您的性能,如果这些字段属于一个对象并且将一起更新,我找不到应该规范化这些字段的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多