【问题标题】:Difference between two table structure两个表结构的区别
【发布时间】:2014-01-13 23:41:24
【问题描述】:

我对这两种结构很困惑。这两张表的优缺点是什么? 哪个更好,为什么?

表 1

id,         name,       age,        birthdate,      address
somedata1   somedata1   somedata1   somedata1       somedata1
somedata2   somedata2   somedata2   somedata2       somedata2
somedata3   somedata3   somedata3   somedata3       somedata3  

表 2

id,         col_name,   col_value

somedata    name        somedata
somedata    age         somedata
somedata    birthdate   somedata
somedata    address     somedata

somedata2   name        somedata2
somedata2   age         somedata2
somedata2   birthdate   somedata2
somedata2   address     somedata2

somedata3   name        somedata3
somedata3   age         somedata3
somedata3   birthdate   somedata3
somedata3   address     somedata3

【问题讨论】:

  • 这真的取决于你的目标。第一个更适合数据类型约束,因为您可以定义/限制插入的值(即确保它是有效日期)。如果您稍后添加更多“属性”,第二个可能会更灵活,因为您不需要修改表结构。每个都有更多的优点/缺点,因此您确实需要了解在存储和查询数据方面您想要做什么。
  • 大多使用第一种结构。如果您一直更改属性,请仅使用第二个。

标签: mysql sql database database-design


【解决方案1】:

反模式?

通常情况下,第二个表在数据库设计的上下文中是反模式。而且,更重要的是,它具有特定的名称:Entity-Attribute-Value (EAV)。在某些情况下,使用这种设计是合理的,但这种情况很少见 - 即使在这种情况下也可以避免。


为什么 EAV 不好

数据完整性支持

尽管这种结构看起来更“灵活”或“先进”,但这种设计有弱点。

  • 无法设置强制属性。您不能强制某些属性,因为属性现在存储为一行 - 并且未设置该属性的唯一标志 - 是表中不存在相应的行。 SQL 将不允许您在本机构建此类约束 - 因此,您必须在应用程序中检查 - 并且,是的,每次都查询您的表
  • 混合数据类型。您将无法使用 SQL 标准数据类型。因为您的值列必须是其中所有存储值的“超类型”。这意味着 - 您通常必须将所有数据存储为 原始字符串。然后你会看到使用日期和字符串、每次转换数据类型、检查数据完整性等是多么痛苦。
  • 无法强制引用完整性。在正常情况下,您可以使用外键来限制您的值,这些值在父表中定义。但不是在这种情况下 - 这是因为参照完整性适用于表中的每一行,但不适用于行值。所以 - 你会失去这个优势 - 它是与数据库相关的基本之一
  • 无法设置属性名称。这意味着 - 您不能正确限制数据库级别的属性名称。例如,您将在第一种情况下将"customer_name" 写为属性名称 - 而另一个开发人员会忘记这一点并使用"name_of_customer"。而且.. 没关系,DB 会通过,您将花费数小时调试此案例。

行重建

此外,行重建在一般情况下会很糟糕。例如,如果您有 5 个属性 - 那将是 5 个自表 JOIN-s。对于这种简单的 - 乍一看 - 案例来说太糟糕了。所以我什至不想想象你将如何维护 20 个属性。


这是否合理?

我的意思是——不。在 RDBMS 中,总会有办法避免这种情况。这太糟糕了。如果打算使用 EAV,那么最好的选择可能是非关系数据库。

【讨论】:

    【解决方案2】:

    在第二种情况下(table2),这很复杂,当我们查询数据时需要花费很多时间来查找数据。当您不知道列数或它们变化时使用这种情况,如果您有固定长度的列,则使用第一种情况(table1),因为在这种情况下数据可以找到快速的方法。

    【讨论】:

      【解决方案3】:

      包含idnameagebirthdateaddress 列的表是当您在部署之前知道要存储有关实体的哪些信息时使用的。

      如果您仅在部署后知道要存储有关实体的哪些信息(例如,如果非技术人员应该能够定义他们希望捕获)。它的效率较低,但允许您在不更改数据库架构的情况下定义新字段。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-11
        相关资源
        最近更新 更多