MySQL數據表優化設計(四):利用枚舉節省存儲空間

枚舉在實際數據表使用中不太多,但是在某些場合卻是可以發揮更好的性能,例如使用枚舉替換有限的字符串值。需要注意的是枚舉的存儲結構有點特殊,本篇介紹枚舉的應用場合及優勢。

枚舉在 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 內部的對照枚舉的過程,性能上也更高,但是數據表的可讀性會差一些。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章