在MySQL 中有兩種數(shù)值類型,整型和實數(shù)(即帶有小數(shù)的數(shù)字)。整型可以通過 TINYINT、SMALLINT、MEDIUMINT、INT 或 BIGINT 表示,分別對應(yīng)8bit、16bit、24bit、32bit 和64bit 的存儲空間。實數(shù)可以通過 FLOAT、DOUBLE 和 DECIMAL 表示,其中 FLOAT 和 DOUBLE 即通常所說的浮點數(shù),由于計算機二進制存儲的精度問題,其計算得到的是近似的結(jié)果。
整型字段類型設(shè)計
整型可以選擇是否是無符號數(shù),這樣可以禁止使用負數(shù),并且可以將存儲的最大值翻倍,例如 TINYINT UNSIGNED類型的字段可以存儲的值的范圍是0-255,而不是有符號的-128-127。使用無符號還是有符號取決與字段類型的范圍,但是如果確定字段是無符號的,那么優(yōu)先選擇無符號類型,因為最大值翻倍可以在一定程度上避免使用更大存儲空間的整型類型。
MySQL 允許我們指定整型的寬度,例如 INT(11)。這對于大部分應(yīng)用并沒有太大意義——實際上 MySQL 并不會限制合法值的范圍,也就是即便指定為 INT(11),實際上只要數(shù)值類型的存儲空間足夠,也可以存儲超過設(shè)定寬度的整型,例如 INT(12)的數(shù)字也可能可以存儲到 INT(11)類型的字段中。對于存儲和計算而言,INT(1)和 INT(20)是等效的。
如果確實要考慮性能,應(yīng)該是根據(jù)業(yè)務(wù)真實的數(shù)值范圍來確定使用整型字段類型,原則是只要字段類型不會超過業(yè)務(wù)系統(tǒng)的數(shù)值最大值,那么盡可能地選擇低存儲長度的整型類型。如果是無符號的數(shù)值,那就盡量使用無符號屬性。例如,假設(shè)使用整型替代枚舉的話,如果枚舉數(shù)量不超過255個,那就優(yōu)先使用 UNSIGNED TINYINT 類型。
實數(shù)
實數(shù)不僅僅可以用來存儲浮點數(shù),實際上還可以使用 DECIMAL 類型來存儲超出 BIGINT 類型的數(shù)值。對于 浮點數(shù),MySQL 支持精確浮點數(shù)類型和不精確浮點數(shù)。
FLOAT 和 DOUBLE 類型支持標(biāo)準(zhǔn)數(shù)學(xué)運算的近似運算,浮點數(shù)的實際計算結(jié)果的精確度依賴于實現(xiàn)浮點數(shù)的平臺。DECIMAL 類型用于存儲精確的浮點數(shù),在 MySQL 5.0以后,DECIMAL 也支持精確的數(shù)學(xué)運算(更早的版本實際上是使用浮點數(shù)來進行 DECIMAL 運算的)。但是,由于 CPU 本身不能直接精確計算浮點數(shù),因此 DECIMAL 數(shù)據(jù)類型的計算速度會比浮點數(shù)要慢。
浮點數(shù)和 DECIMAL 都支持指定精度。DECIMAL 類型的可以分別指定小數(shù)點前后最大的數(shù)字位數(shù),這會影響數(shù)據(jù)列的存儲空間占用。MySQL5.0版本以后將數(shù)字位以二進制形式存儲(每9位數(shù)使用4個字節(jié)存儲)。例如 DECIMAL(18, 9)將在小數(shù)點兩側(cè)均為9位數(shù)字,算上小數(shù)點(占一個字節(jié)),總共需要9個字節(jié)來存儲。DECIMAL 最大的數(shù)字位數(shù)是65(包含小數(shù)位和整數(shù)位),例如下面的表表創(chuàng)建語句會報錯提示#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 那種方式指定整數(shù)位和小數(shù)位來確定存儲范圍和精度。不同的長度會使得 MySQL默認(rèn)選擇不同的數(shù)據(jù)類型并使用近似值存儲數(shù)據(jù)。FLOAT 類型的存儲長度固定為4個字節(jié), DOUBLE 類型的存儲長度固定為8個字節(jié)。精度是不確定的,指定精度對存儲空間并沒有幫助,因此從計算準(zhǔn)確度考慮,建議是不要指定精度。在內(nèi)部計算的時候,MySQL 會選擇使用 DOUBLE類型計算 FLOAT 類型的數(shù)據(jù)。
由于 DECIMAL 占據(jù)的空間更大以及計算資源消耗也更大,因此建議只有在需要精確表示數(shù)值的情況下選擇使用 DECIMAL(例如金融數(shù)據(jù),如金額)。如果考慮計算性能,也可以考慮使用 BIGINT 來存儲精確的浮點數(shù),例如將金額統(tǒng)一乘以固定的倍數(shù)轉(zhuǎn)換為 BIGINT 進行運算,這種方式的計算效率和存儲空間都會更小。