我的几个表的列可以是ENUM
类型或INT
类型。我倾向于总是使用整数类型,假设基于它执行搜索会更快。
例如,我的一个表格中有一列:StatusType
,其中只有4个可能的值:Completed
,In Progress
,Failed
,Todo
。
不是将上面的ENUM
字符串存储起来,而是将它们存储为:
1
,2
,3
,4
。然后在我的PHP代码中,我有一些常量变量来定义这些值:
define('COMPLETED', 1);
define('IN_PROGRESS', 2);
define('FAILED', 3);
define('TODO', 4);
现在我的问题是,我是按照正确的方式做的,还是应该将其更改为ENUM
类型并在查询中使用字符串进行比较?我还有许多其他列只能设置最大4-5
个可能的值。
答案 0 :(得分:8)
评论太长了。
在MySQL中,枚举值看起来很酷,但我不是他们的粉丝。它们限制为255个值,因此如果您决定添加更多值,则可能会遇到限制。此外,正如您所描述的,您需要将应用程序代码中的值与数据库中的值同步 - 这似乎是有潜在危险的。
此外,它们使未来的某些变化更加困难。例如,其他数据库不支持枚举。而且,如果您想添加多语言支持,在数据库中嵌入数据类型定义中的代码有点难以处理。
更标准的方法是一个或多个参考表,您可以使用join
来获取值。您可以使用混合方法,在数据库中使用引用表。然后,你可以将引用表加载到应用程序中,以获得从数字到字符串的映射,这样就可以避免代码中的连接。
答案 1 :(得分:2)
你是正确的。从绩效角度看,Enum非常糟糕:MySQL Enum performance advantage?
也就是说,将INT
s的定义绑定到您的代码也不是一件好事。理想情况下,如果要遵循正确的数据规范化模式,则还要在另一个表中定义数据库中INT
的值,并使用定义的索引作为赋值的值。
请参阅:http://en.wikipedia.org/wiki/Database_normalization#Normal_forms
这样做的原因是数据是可移植的,并且无需Codebase读取它就很有用(您可以通过执行连接轻松地转储CSV for Excel)。
神速。
示例SQL:
SELECT *, state.name AS state FROM students
JOIN states ON student.state_id = states.id
只是为了得到州名。
或过滤:
SELECT * FROM students
JOIN states ON student.state_id = states.id
WHERE state.name = 'Maine' OR state.code = 'ME'
是的,奇怪的例子,但我的想法是INT
是TINY,而VARCHAR
是...变量......存储'缅因州'而不是' 16'累计超过数百万行。此外,INT
上的索引比VARCHAR
快得多,因此您的查找速度会快得多。特别是如果您提前知道数字并在没有JOIN
的情况下构建查询。这不是一种常见的做法,但如果您想要更快地制作某些内容并且可以确保假定值的有效性,则可以这样做。
答案 2 :(得分:2)
首先,我建议和@ GordonLinoff一起回答。他对ENUM类型的看法与我的相符。它似乎没有任何真正积极的事情。我将此作为单独的答案添加,因为它在数据库体系结构中经常被忽略。
戈登的回答,我对它的补充评论表明,规范化是可行的方法。将整数键存储在大表中,并将值存储在单独的表中。每个键/值对的不同表。这是95%的应用程序的正确方法。无论如何,我会避免在PHP中存储您的价值。只要您需要添加新的键/值对,就必须编辑代码,并且应该避免这样做。
你说这个表主要是READ,所以我认为考虑非规范化数据很重要。我仍然没有建议使用ENUM,因为我认为数据验证/限制应该是您的前端而不是数据库的函数,但您可能会发现在主表中存储实际值而不是键是有利的。 JOIN对于READ应用程序来说是昂贵的,因此将值直接粘贴到您要读取的表中并正确地索引它们将使所有内容保持运行。
通常,当我们处理应用程序是事务性(WRITE)但具有报告要求(READ)时,我们优化WRITE并对模式进行大规模标准化,但为了满足我们对报告方面快速READ的需求,我们重写了单独表中严重非规范化的数据。我们尝试将尽可能多的字段粉碎到单个表中。通常将密钥和值存储在同一个表中。这会产生巨大的丑陋数据,但读取速度要快得多。
与大多数数据库架构练习一样,您必须执行适合您的应用程序的操作。它通常是平衡相互冲突的要求和牺牲理智速度的问题。