MySQL 數據表優化設計(二):數值字段類型如何選擇?

在MySQL 中有兩種數值類型,整型和實數(即帶有小數的數字)。整型可以通過 TINYINT、SMALLINT、MEDIUMINT、INT 或 BIGINT 表示,分別對應8bit、16bit、24bit、32bit 和64bit 的存儲空間。實數可以通過 FLOAT、DOUBLE 和 DECIMAL 表示,其中 FLOAT 和 DOUBLE 即通常所說的浮點數,由於計算機二進制存儲的精度問題,其計算得到的是近似的結果。

整型字段類型設計

整型可以選擇是否是無符號數,這樣可以禁止使用負數,並且可以將存儲的最大值翻倍,例如 TINYINT UNSIGNED類型的字段可以存儲的值的範圍是0-255,而不是有符號的-128-127。使用無符號還是有符號取決與字段類型的範圍,但是如果確定字段是無符號的,那麼優先選擇無符號類型,因爲最大值翻倍可以在一定程度上避免使用更大存儲空間的整型類型。

MySQL 允許我們指定整型的寬度,例如 INT(11)。這對於大部分應用並沒有太大意義——實際上 MySQL 並不會限制合法值的範圍,也就是即便指定爲 INT(11),實際上只要數值類型的存儲空間足夠,也可以存儲超過設定寬度的整型,例如 INT(12)的數字也可能可以存儲到 INT(11)類型的字段中。對於存儲和計算而言,INT(1)和 INT(20)是等效的。

如果確實要考慮性能,應該是根據業務真實的數值範圍來確定使用整型字段類型,原則是隻要字段類型不會超過業務系統的數值最大值,那麼儘可能地選擇低存儲長度的整型類型。如果是無符號的數值,那就儘量使用無符號屬性。例如,假設使用整型替代枚舉的話,如果枚舉數量不超過255個,那就優先使用 UNSIGNED TINYINT 類型。

實數

實數不僅僅可以用來存儲浮點數,實際上還可以使用 DECIMAL 類型來存儲超出 BIGINT 類型的數值。對於 浮點數,MySQL 支持精確浮點數類型和不精確浮點數。

FLOAT 和 DOUBLE 類型支持標準數學運算的近似運算,浮點數的實際計算結果的精確度依賴於實現浮點數的平臺。DECIMAL 類型用於存儲精確的浮點數,在 MySQL 5.0以後,DECIMAL 也支持精確的數學運算(更早的版本實際上是使用浮點數來進行 DECIMAL 運算的)。但是,由於 CPU 本身不能直接精確計算浮點數,因此 DECIMAL 數據類型的計算速度會比浮點數要慢。

浮點數和 DECIMAL 都支持指定精度。DECIMAL 類型的可以分別指定小數點前後最大的數字位數,這會影響數據列的存儲空間佔用。MySQL5.0版本以後將數字位以二進制形式存儲(每9位數使用4個字節存儲)。例如 DECIMAL(18, 9)將在小數點兩側均爲9位數字,算上小數點(佔一個字節),總共需要9個字節來存儲。DECIMAL 最大的數字位數是65(包含小數位和整數位),例如下面的表表創建語句會報錯提示#1426 - Too-big precision 66 specified for 'number'. Maximum is 65.

CREATE TABLE t_numbers ( 
  id INT(11) AUTO_INCREMENT PRIMARY KEY, 
  number DECIMAL(66,1) 
);

對於 FLOAT 和 DOUBLE類型,也可以類似 DECIMAL 那種方式指定整數位和小數位來確定存儲範圍和精度。不同的長度會使得 MySQL默認選擇不同的數據類型並使用近似值存儲數據。FLOAT 類型的存儲長度固定爲4個字節, DOUBLE 類型的存儲長度固定爲8個字節。精度是不確定的,指定精度對存儲空間並沒有幫助,因此從計算準確度考慮,建議是不要指定精度。在內部計算的時候,MySQL 會選擇使用 DOUBLE類型計算 FLOAT 類型的數據。

由於 DECIMAL 佔據的空間更大以及計算資源消耗也更大,因此建議只有在需要精確表示數值的情況下選擇使用 DECIMAL(例如金融數據,如金額)。如果考慮計算性能,也可以考慮使用 BIGINT 來存儲精確的浮點數,例如將金額統一乘以固定的倍數轉換爲 BIGINT 進行運算,這種方式的計算效率和存儲空間都會更小。

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