《高效能MySQL》筆記 列舉(ENUM)型別

2021-08-15 15:10:17 字數 1934 閱讀 6508

有時候可以使用列舉列代替常用的字串型別。列舉列可以把一些不重複的字串儲存成乙個預定義的集合。mysql在儲存列舉時非常緊湊,會根據列表值的數量壓縮到乙個或者兩個位元組中。mysql在內部會將每個值在列表中的位置儲存為整數,並且在表的.frm檔案中儲存「數字-字串」對映關係的「查詢表」。下面有乙個例子:

這三行資料實際儲存為整數,而不是字串。可以通過在數字上下文環境檢索看到這個雙重屬性:

如果使用數字作為enum列舉常量,這種雙重性很容易導致混亂,例如enum(『1』,』2』,』3』)。建議盡量避免這麼做。

另外乙個讓人吃驚的地方是,列舉欄位是按照內部儲存的整數而不是定義的字串進行排序的:

一種繞過這種限制的方式是按照需要的順序來定義列舉列。另外也可以在查詢中使用field()函式顯示地指定排序順序,但這會導致mysql無法利用索引消除排序。

如果在定義時就是按照字母的順序,就沒有必要這麼做了。

列舉最不好的地方是,字串列表是固定的,新增或刪除字串必須使用alter table。因此,對於一些列未來可能會改變的字串,使用列舉不是乙個好主意,除非能接受只在列表末尾新增元素,這樣在mysql5.1中就可以不用重建整個表來完成修改。

由於mysql把每個列舉值儲存為整數,並且必須進行查詢才能轉換為字串,所以列舉列有一些開銷。通常列舉的列表都比較小,所以開銷還可以控制,但也不能保證一直如此。在特定情況下,把char/varchar列與列舉列進行關聯可能會比直接關聯char/varchar列更慢。

為了說明這個情況,我們對乙個應用中的一張表進行基準測試,看看在mysql中執行上面說的關聯的速度如何。該錶有乙個很大的主鍵:

這個表有11萬行資料,只有10mb大小,所以可以完全載入記憶體。service列包含了5個不同的值,平均長度為4個字元,method列包含了71個值,平均長度為20個字元。我們複製一下這個表,但是把service和method欄位換成列舉型別,表結構如下:

然後我們用主鍵列關聯這兩個表,下面是所使用的查詢語句:

我們用varchar和enum分別測試了這個語句,結果入標4-1所示。

從上年的結果可以看到,當把列都轉換成enum以後,關聯變得很快。但是當varchar列和enum列進行關聯時則慢很多。在本例中,如果不是必須和varchar列進行關聯,那麼轉換這些列為enum就是個好主意。這是乙個通用的設計實踐,在「查詢表」時採用整數主鍵而避免採用基於字串的值進行關聯。

然而,轉換列為列舉型還有另乙個好處。根據show table status命令輸出結果中data_length列的值,把這兩列轉換為enum可以讓表的大小縮小1/3。在某些情況下,即使可能出現enum和varchar進行關聯的情況,這也是值得的。同樣,轉換後主鍵也只有原來的一半大小了。因為這是innodb表,如果表上有其他索引,減小主鍵大小會使非主鍵索引也變得更小。

建立高效能索引 《高效能Mysql》筆記2

crate table people last name varchar 50 not null,first name varchar 50 not null,dob date not null,gender enum m f not null,key last name,first name,do...

讀高效能mysql筆記

效能監控的好工具 newrelic 效能分析的好工具 percona toolkit show variables like slow show full processlist set profiling 1 select from score cal unsuccessed show profi...

《高效能MySQL》筆記(2)

mysql儲存 的四種形式 1.觸發器 2.儲存過程 3.函式 4.在定時任務中存放 5.1開始 即事件 儲存過程和儲存函式可以接收引數然後返回值,但是觸發器和事件卻不行 mysql儲存過程 儲存過程 是一組為了完成特定功能的sql語句集,經編譯後儲存在資料庫中,使用者通過指定儲存過程的名字並給定引...