枚举在实际数据表使用中不太多,但是在某些场合却是可以发挥更好的性能,例如使用枚举替换有限的字符串值。需要注意的是枚举的存储结构有点特殊,本篇介绍枚举的应用场合及优势。
枚举在 MySQL 中的存储方式十分精简,依据枚举值的多少使用1-2个字节来存储。枚举在内部实际是使用整数代表列在对应枚举值的位置,然后在数据表中有一个后缀为.frm 的对照表文件存储枚举真实对应的值。以下面的表为例:
CREATE TABLE t_enum_test (
gender ENUM('male', 'female', 'unknown') NOT NULL
);
INSERT INTO t_enum_test(gender) VALUES('male'), ('female'), ('unknown');
这个表的列实际是可以用于整数计算的,而且运算的结果是按整数返回的:
SELECT gender+0 FROM t_enum_test;
得出的结果实际是1,2,3。因此,如果你的枚举值是没有意义的数字的话,例如 ENUM('1', '2', '3'),那会导致很困惑,因此建议不要使用无意义的值或数字作为枚举。另外一个是,枚举的排序不是按枚举的字符串值来定的,而是基于其数字值。例如:
SELECT gender FROM t_enum_test ORDER BY gender DESC;
实际的次序并不是想象中的按字符串倒序的 unknown, male 和 female,而是 unknown, female 和 male。因此如果想要准确的排序,就需要指定按字段值排序:
SELECT gender FROM t_enum_test
ORDER BY FIELD(gender, 'unknown', 'female', 'male') DESC;
这时候次序会按照指定的次序一次排列,可以使用 DESC 和 ASC 明确方向,但这个方向不是枚举值的排序,而是次序的变换。例如上面返回的结果是 male,female 和 unknown。因此,如果想要按次序使用枚举值排序,最好创建表的时候枚举值就是升序排列的。
枚举最大的缺陷是可选值是固定的,增加或减少枚举值都需要使用 ALTER TABLE 操作。因此,如果待选的字符串经常变化,那就不适用于枚举。当然,在 MySQL 5.1以后,往枚举结尾添加枚举值不会对重建整个表。同时,由于 MySQL 使用整型存储枚举,每次查询都需要转换为对应的字符串值,因此会带来一定的额外开销。这个开销通常受枚举值多少的影响。但是枚举值的优势也是显而易见的,使用枚举值的数据表列存储空间相比字符串更小。
在实际应用中,还有一种更为实际的做法,就是将枚举值当做整型存储到数据表中,然后在应用中实现类似 MySQL 的枚举查找表,通过这种方式可以减少 MySQL 内部的对照枚举的过程,性能上也更高,但是数据表的可读性会差一些。
网友评论