簡體   English   中英

MySQL ENUM 類型與連接表

[英]MySQL ENUM type vs join tables

我的要求

一個表需要維護一個狀態列。

此列代表 5 個州之一。


初始設計

我想我可以將其設為整數列並使用數值表示狀態。

  • 0 = 開始
  • 1 = 運行
  • 2 = 崩潰
  • 3 = 暫停
  • 4 = 停止

由於我不希望我的應用程序維護從整數到其字符串描述的映射,因此我計划將它們放在單獨的狀態描述表中(依賴於 FK 關系)。

然后我發現 MySQL 有一個 ENUM 類型完全符合我的要求。 除了直接依賴 MySQL 之外,使用 ENUM 類型是否有任何陷阱?

  • 更改 ENUM 中的一組值需要一個ALTER TABLE ,這可能會導致表重組——一個非常昂貴的操作(如果您只是在 ENUM 定義的末尾添加一個新值,則不會發生表重組,但是如果您刪除一個或更改順序,它會進行表重組)。 而更改查找表中的值集就像 INSERT 或 DELETE 一樣簡單。

  • 無法將其他屬性與 ENUM 中的值相關聯,例如哪些屬性已停用,哪些屬性可以放入用戶界面的下拉列表中。 但是,查找表可以包含此類屬性的附加列。

  • 查詢 ENUM 以獲取不同值的列表非常困難,基本上需要您從INFORMATION_SCHEMA查詢數據類型定義,並從返回的 BLOB 中解析列表。 您可以嘗試從表中SELECT DISTINCT status ,但這只會獲取當前使用的狀態值,這可能不是 ENUM 中的所有值。 但是,如果您將值保存在查找表中,則很容易查詢、排序等。

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

這同樣適用於簡單地將列與一組固定值進行比較的 CHECK 約束。 盡管 MySQL 不支持 CHECK 約束。

更新:MySQL 8.0.16 現在實現了CHECK 約束

這是關於enum 速度比較的文章。 也許它給出了一些提示。 恕我直言,它應該僅限於在固定的字符串列表(“是/否”,“兒童/成人”)中使用,99% 的概率在未來不會改變。

由於已經解釋的原因,MySQL 中的枚舉不好。
我可以添加以下事實:枚舉不確保在服務器端進行任何類型的驗證。 如果您插入一個值在枚舉定義中不存在的行,您將在數據庫中獲得一個不錯的<empty>NULL值,具體取決於枚舉字段聲明的 NULL 能力。

我對 tinyints 的看法:

  • 枚舉限制為 65535 個值
  • 如果您不需要超過 256 個值,則 tinyint 將為每一行占用更少的空間,並且它的行為更加“可預測”。

如果你的數據庫中有很多數據(更多的數據然后你有 RAM)並且你的 ENUM 值永遠不會改變,我會選擇 ENUM,而不是加入。 它應該更快。
想想看,在連接的情況下,您需要一個外鍵索引和另一個表中主鍵的索引。 正如 Riho 所說,請參閱基准。

一張表會更容易國際化。 但是完全在數據庫之外的類也是如此。 當不在業務邏輯中時,這種檢查可能很難調試,並且通常不是數據庫人員的責任。

作為一種優化,它可能還為時過早。 但無論如何,OP 主要將其作為一種便利功能提出來。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM