【问题标题】:What is the downside of structuring SQL tables this way? [closed]以这种方式构建 SQL 表的缺点是什么? [关闭]
【发布时间】:2017-01-03 07:43:54
【问题描述】:

假设我想创建一个这样的表:

id | some_foreign_id | attribute | value
_________________________________________
1           1            Weight     100
2           1            Reps       5
3           2            Reps       40
4           3            Time       10
5           4            Weight     50
6           4            Reps       60

与以这种方式表示的相同数据相比

id | some_foreign_id | weight | reps | time
____________________________________________
1           1           100      5     NULL
2           2           NULL     40    NULL
3           3           NULL     NULL  10
4           4           50       60    NULL

因为在这种情况下 id = foreign_id 我认为我们可以将这些列附加到foreign_id 所指的任何表中。

我假设大多数人会绝大多数人说后一种方法是公认的做法。

前一种方法是否被认为是一个坏主意,即使它不会导致任何 NULL 值?这两种方法之间的权衡究竟是什么?似乎前者可能更通用,但代价是没有明确定义的结构,但我不知道这是否真的会导致其他后果。我可以想象在后一个示例中有大量列的情况,其中大部分为 NULL,并且可能只填充了三个不同的值。

【问题讨论】:

  • 第一个是使用所谓的实体值属性模型。 en.wikipedia.org/wiki/Entity-attribute-value_model 有人讨厌,有人知道怎么用。在此处研究您的选择。
  • @Twelfth 你会说这两种方法都是合理的吗?如果有很多列,你会使用 EAV 模型吗?查询和连接呢?
  • @Twelfth 我知道它是实体属性值模型,因此是 EAV 的缩写;-)
  • 如果您要使用 EAV,请考虑根据数据类型将不同的属性分离到单独的表中。因此,您可能有一个 DECIMAL 类型属性表和另一个 DATE 类型属性表。
  • @Strawberry 我不太明白你的意思。您是说基本上为每一列创建一个新表吗?

标签: mysql sql database sqlite normalization


【解决方案1】:

EAV 是您的第一个示例所在的模型。它有一些优点,但是您在 mysql 中,而 mysql 不能最好地处理这个问题。正如该线程中所指出的Crosstab View in mySQL? mysql 缺少其他数据库具有的功能。 Postgres 和其他数据库有一些更有趣的函数PostgreSQL Crosstab Query,使这变得更加容易。在 MSSQL 世界中,这被称为稀疏填充列。我发现柱状结构实际上非常适合这个(垂直或高端甲骨文)

优点:

  • 向其中添加新列比更改表架构要容易得多。如果您不确定将来的列名称是什么,那么可以这样做

  • 稀疏填充的列会导致表中充满空值和冗余数据。您可以设置逻辑来为列创建“默认”值...如果没有为此属性指定值,则使用此值。

缺点:

  • 在 MySQL 中编程有点困难,特别是根据上面的 cmets。并非所有 SQL 开发人员都熟悉该模型,您可能会意外地为新资源实现更陡峭的学习曲线。

  • 不是最可扩展的。索引是一个挑战,你需要解决(草莓在 cmets 中的输入是针对这个的,你的值列基本上是强制为 Varchar 并且索引不好,也不容易搜索......欢迎来到表扫描地狱)。尽管您可以使用第三个表来解决此问题(例如,您查询诸如创建日期和关闭日期之类的日期。创建第三个“控制”表,其中包含那些经常查询的列和索引……从那里引用 EAV 表) 或创建多个 EAV 表,每种数据类型一个。

【讨论】:

    【解决方案2】:

    第一个是正确的。

    • 如果以后你想改变属性的数量,你不必改变你的数据库结构。

      • 更改数据库结构可能会导致您的应用崩溃。
    • 如果 null 的数量太大,则会浪费大量存储空间。

    【讨论】:

    • 但是执行查询变得更难了吗?由于不再将它们编码为列,因此执行联接之类的操作会变得更加困难吗?
    • 嗯,也许取决于你打算如何使用它,你可以获得一点好处。但就存储和可扩展性而言,第一个选项的效率要高得多。更难的是一个相对术语。一旦你知道如何去做,它一点也不难。 db 旨在处理这类表格。
    【解决方案3】:

    我对此的看法 如果我想以更动态的方式添加许多不同的属性和值,我可能会使用第一个,例如用户标签或用户特定信息等,

    如果我只有三个属性(如您的示例)重量、次数、时间并且不需要任何动态或需要添加更多属性(如果是这种情况,我可能会使用第二个)只需添加另一列)

    我会说两者都有效,正如您自己所说,“前者可能更通用”。两种方式都需要自己的结构来提取、处理和存储数据:)

    编辑:要使第一个实现第二个的结构,您必须为要包含在数据提取中的每个属性添加一个连接。

    【讨论】:

      【解决方案4】:

      我认为第一种方式对规范化有更好的贡献。你甚至可以创建一个带有属性的新表:

      id  attribute
      ______________
      1   reps
      2   weight
      3   time
      

      然后把倒数第二列变成一个外来的id。这将节省空间并避免错误输入属性名称的风险。像这样:

      id | some_foreign_id | attribute | value
      _________________________________________
      1           1            2         100
      2           1            1         5
      3           2            1         40
      4           3            3         10
      5           4            2         50
      6           4            1         60
      

      【讨论】:

        【解决方案5】:

        正如其他人所说,第一种方法是更好的方法。为什么?好吧,它使结构标准化。参考:https://en.wikipedia.org/wiki/Database_normalization

        正如那篇文章所述,规范化可减少数据库大小并便于扩展。

        【讨论】:

          猜你喜欢
          • 2014-01-30
          • 1970-01-01
          • 1970-01-01
          • 2012-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-24
          相关资源
          最近更新 更多