Postgresql

當 PostgreSQL 的“類別”太多時,我應該使用列舉嗎?

  • January 31, 2020

問題

我計劃將包含更多 1000 萬條記錄的 CSV 載入到 PostgreSQL v12.1 中,其中一個列具有“分類”值,因此為其創建列舉類型似乎是一個不錯的選擇,但它包含 208 個類別。

最短的欄位為 2,最長的欄位為 11 個字元。所有欄位的平均值為 2.4。字元編碼是 UTF8,但所有字元都是 ASCII

問題:

我應該使用哪種類型enumeratedvarchar

附加資訊

我放棄了char因為官方 PostgreSQL 文件說明了關於charvarchartext的以下內容:

提示:這三種類型之間沒有性能差異,除了在使用空白填充類型時增加了儲存空間,以及在儲存到長度受限的列時需要一些額外的 CPU 週期來檢查長度。雖然 character(n) 在其他一些數據庫系統中具有性能優勢,但在 PostgreSQL 中沒有這樣的優勢;事實上 character(n) 通常是三個中最慢的,因為它有額外的儲存成本。在大多數情況下,應改為使用文本或字元變化。

PostgreSQL 中的列舉值在磁碟上佔用4 個字節(參見 8.7.4. 實現細節)。考慮到這一點以及使用enum類型的 2.4 平均字元串長度會導致磁碟使用率稍高(PostgreSQL 中的短字元串需要一個額外的字節磁碟空間)。我仍然認為使用 enum 是一個更好的選擇,因為它的實現使許多操作對它更快。

平均有 2.4 個字元(更相關:平均字節數- 但對於所有 ASCII 字元都是一樣的),我不會費心使用列舉。這些佔用磁碟上的 4 個字節,可能還有對齊填充。(text不需要對齊填充。)您甚至沒有節省儲存空間並為此獲得更多成本。

大多數值低於 7 個字元(= 磁碟上的 8 個字節),text類別列上的索引也只會比enum. (數據空間(通常)以 8 個字節的倍數分配。)

對於固定數量的 208 個類別,"char"編碼(不要與char! 混淆)可能是節省儲存空間的一個選項。看:

但是,再一次,這麼小的字元串不值得麻煩。只需使用text. 也許使用FK 約束對錶強制正確性,category例如:

CREATE TABLE category (category text PRIMARY KEY);

也是儲存每個類別的附加資訊的好地方。您可以輕鬆地修改類別集。進行 FK 約束ON UPDATE CASCADE,您可以在一個中心位置更改類別名稱。製作它ON DELETE SET NULL,您可以輕鬆刪除一個類別。等等。

有關的:

引用自:https://dba.stackexchange.com/questions/258588