【问题标题】:MySQL ENUM type vs join tablesMySQL ENUM 类型与连接表
【发布时间】:2010-09-26 14:20:32
【问题描述】:

我的要求

一张表需要维护一个status列。

此列代表 5 个州之一。


初始设计

我想我可以将其设为整数列并使用数值表示状态。

  • 0 = 开始
  • 1 = 正在运行
  • 2 = 崩溃
  • 3 = 暂停
  • 4 = 停止

由于我不希望我的应用维护从整数到其字符串描述的映射,因此我计划将它们放在单独的状态描述表中(依赖于 FK 关系)。

然后我发现 MySQL 有一个 ENUM 类型完全符合我的要求。 除了直接依赖 MySQL 之外,使用 ENUM 类型有什么陷阱吗?

【问题讨论】:

标签: mysql database-design enums


【解决方案1】:
  • 更改 ENUM 中的值集需要 ALTER TABLE,这可能会导致表重组——一个非常昂贵的操作(如果您只是在末尾添加一个新值,则不会发生表重组ENUM 定义,但如果您删除一个或更改顺序,它会进行表重组)。而更改查找表中的值集就像 INSERT 或 DELETE 一样简单。

  • 无法将其他属性与 ENUM 中的值相关联,例如哪些属性已停用,哪些可以放入用户界面的下拉列表中。但是,查找表可以包含此类属性的其他列。

  • 查询一个 ENUM 得到一个不同值的列表非常困难,基本上需要你从INFORMATION_SCHEMA 查询数据类型定义,并从返回的 BLOB 中解析出列表。您可以从表中尝试SELECT DISTINCT status,但这只会获取当前正在使用的状态值,这可能不是 ENUM 中的所有值。但是,如果将值保存在查找表中,则很容易查询、排序等。

如您所知,我不是 ENUM 的忠实粉丝。 :-)

这同样适用于简单地将列与一组固定值进行比较的 CHECK 约束。虽然 MySQL 不支持 CHECK 约束。

更新:MySQL 8.0.16 现在实现了CHECK constraints

【讨论】:

  • 感谢比尔的提示。有时像 ENUM 类型这样的抽象可能看起来简单而优雅,但却是一个管理定时炸弹。
  • 哦,我忘了一个:ENUM 不是标准 SQL,AFAIK 没有其他品牌的数据库支持它。所以如果你使用它,它会限制你的便携性。
  • 有人给我投了反对票。当你投反对票时,你能解释一下你的反对意见是什么吗?也许我可以改进答案。
  • 您不必使用INFORMATION_SCHEMA。使用DESC table,遍历结果直到找到所需的字段,然后使用正则表达式获取字段。这不是一件好事,但也没有那么糟糕。
  • 我发现了另一个有趣的解释:komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil
【解决方案2】:

这是关于speed comparison of enum的文章。也许它给出了一些提示。 恕我直言,它应该仅限于在固定的字符串列表(“是/否”、“儿童/成人”)中使用,99% 的概率在未来不会改变。

【讨论】:

    【解决方案3】:

    由于已经解释的原因,MySQL 中的枚举不好。
    我可以添加以下事实:枚举不确保在服务器端进行任何类型的验证。如果您插入一个值在枚举定义中不存在的行,您将在 DB 中获得一个不错的 <empty>NULL 值,具体取决于枚举字段声明的 NULL 能力。

    我对 tinyints 的看法:

    • 枚举限制为 65535 个值
    • 如果您不需要超过 256 个值,则 tinyint 将占用更少的每一行空间,并且其行为更加“可预测”。

    【讨论】:

    • 等等,枚举或小整数不好吗?还是两者兼而有之?
    • 很确定他的意思是说“枚举”是不好的原因。
    • 至少在 MySQL 中,如果您将 SQL_MODE 设置为其中一种严格的形式,如果您尝试插入不在 ENUM 中的值,您将不会得到 null 或 ''。你会得到一个错误。见dev.mysql.com/doc/refman/5.7/en/constraint-enum.html
    【解决方案4】:

    如果您的数据库中有大量数据(更多数据然后您有 RAM)并且您的 ENUM 值永远不会改变,我会选择 ENUM,而不是连接。它应该更快。
    想一想,在连接情况下,您需要一个外键索引和另一个表中主键的索引。正如 Riho 所说,请参阅基准。

    【讨论】:

      【解决方案5】:

      表格更容易国际化。但是完全在数据库之外的类也是如此。 当不在业务逻辑中时,这种检查可能很难调试,并且通常不是数据库人员的责任。

      作为一种优化,它可能还为时过早;但无论如何,OP 主要将其作为一种便利功能提出来。

      另见http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-09
        • 2017-07-25
        • 1970-01-01
        • 2023-04-06
        • 2010-11-30
        • 2010-09-20
        相关资源
        最近更新 更多