前言
MySQL(5.6)的數據類型非常多,大致可以分爲四大類:numeric types(數值類型)、date and time types(日期和時間類型)、string (character and byte) types(字符串/字符/字節類型)、spatial types(空間類型)。
四大類共有32種,如何選取合適的數據類型,也是一個非常重要的問題。當表中數據量比較小的時候,不能凸顯數據類型的重要性,一旦數據量大了之後,不合適的數據類型會帶來非常大的麻煩。
本篇主要講解數值類型、日期時間類型和字符串類型三種。
numeric types
numeric types
(數值類型)又可以分爲整數、定點數和浮點數,對應的類型分別如下
整數
對於整數數據類型,都可以表示成type[(M)] [UNSIGNED] [ZEROFILL]
的形式,M
表示最大顯示寬度。最大顯示寬度爲255。顯示寬度與類型可以存儲的值的範圍無關。
UNSIGNED
、ZEROFILL
是兩個額外的屬性,分別表示:是否有符號,是否填充0。
對於浮點和定點數據類型,M
是可以存儲的總位數。 如果爲數字列指定ZEROFILL
,MySQL會自動將UNSIGNED
屬性添加到該列。
數據類型 | 大小 | 範圍 | 解釋 |
---|---|---|---|
tinyint |
1 byte | 有符號類型範圍:[-128, 127] 無符號類型範圍:[0, 255] |
非常小的整數 |
smallint |
2 byte | 有符號類型範圍:[-32768, 32767] 無符號類型範圍:[0, 65535] |
小整數值 |
mediumint |
3 byte | 有符號類型範圍:[-8388608, 8388607] 無符號類型範圍:[0, 16777215] |
中等整數值 |
int / integer |
4 byte | 有符號類型範圍:[-2147483648, 2147483647] 無符號類型範圍:[0, 4294967295] |
整數值 |
bigint |
8 byte | 有符號類型範圍:[-9223372036854775808, 9223372036854775807] 無符號類型範圍:[0, 18446744073709551615] |
極大整數值 |
定點數
對於定點數據類型,都可以表示成type[(M[, D])] [UNSIGNED] [ZEROFILL]
的形式,看起來有點繞,實際上是存在三種寫法:type
、type(M)
、type(M, D)
。其中M
是可以存儲的總位數,D
是小數點後的位數(小數位數)。小數點和(對於負數)符號不計入M
。如果D
爲0,則值沒有小數點或小數部分。
數據類型 | 解釋 |
---|---|
decimal / dec / numeric / fixed |
decimal 的最大位數(M )爲65。支持的小數位數(D )的最大值爲30。如果省略 D ,則默認值爲0。如果省略M ,則默認值爲10。使用 decimal 列的所有基本計算(+,-,*,/)均以65位精度完成。fixed 可用於與其他數據庫系統兼容。 |
浮點數
浮點數包括float
和double
兩種類型
數據類型 | 解釋 |
---|---|
float[(M,D)] |
單精度浮點數。M 是總位數,D 是小數點後的位數。如果省略M 和D ,則將值存儲到硬件允許的極限。單精度浮點數的精度約爲小數點後7位FLOAT(M,D) 是非標準的MySQL擴展 |
float(p) |
浮點數。 p 表示位精度,但是MySQL僅使用此值來確定對結果數據類型使用FLOAT 還是DOUBLE 。如果p 從0到24,則數據類型爲FLOAT ,沒有M 或D 值。如果p 爲25到53,則數據類型將變爲DOUBLE ,且沒有M 或D 值。FLOAT(p) 語法以實現ODBC兼容性 |
double[(M,D)] / double precision[(M,D)] / real[(M,D)] |
雙精度浮點數。M 是總位數,D 是小數點後的位數。如果省略M 和D ,則將值存儲到硬件允許的極限。雙精度浮點數精確到大約15個小數位DOUBLE(M,D) 是非標準的MySQL擴展如果啓用 REAL_AS_FLOAT SQL模式,則REAL 是FLOAT 的同義詞,而不是DOUBLE |
date and time types
用於表示時間值的日期和時間數據類型爲DATE
,TIME
,DATETIME
,TIMESTAMP
和YEAR
。
類型 | 解釋 | 零值 |
---|---|---|
date |
日期類型,支持的範圍:[‘1000-01-01’, ‘9999-12-31’] MySQL以 YYYY-MM-DD 格式顯示date 值,但允許使用字符串或數字將值分配給date 列 |
'0000-00-00' |
datetime[(fsp)] |
日期和時間組合,支持的範圍:[‘1000-01-01 00:00:00.000000’, ‘9999-12-31 23:59:59.999999’] MySQL以 YYYY-MM-DD hh:mm:ss[.fraction] 的格式顯示datetime 值,但允許使用字符串或數字將值分配給datetime 列fsp 表示小數位數,範圍:[0, 6],如果不指定,默認爲0,表示沒有小數支持自動初始化和更新 |
'0000-00-00 00:00:00' |
timestamp[(fsp)] |
時間戳類型,支持範圍:('1970-01-01 00:00:01.000000’UTC, '2038-01-19 03:14:07.999999’UTC]fsp 表示小數位數,範圍:[0, 6],如果不指定,默認爲0,表示沒有小數 |
'0000-00-00 00:00:00' |
time[(fsp)] |
時間類型,支持範圍:[’-838:59:59.000000’, ‘838:59:59.000000’] MySQL以 hh:mm:ss[.fraction] 的格式顯示time 值,但允許使用字符串或數字將值分配給time 列fsp 表示小數位數,範圍:[0, 6],如果不指定,默認爲0,表示沒有小數 |
'00:00:00' |
year[(2|4)] |
2位或4位格式的年份。默認值爲4位數字格式。 YEAR(2)或YEAR(4)的顯示格式不同,但是值的範圍相同。 在4位數格式中,值顯示爲:[1901, 2155],或者0000。 在2位數格式中,值顯示爲70至69,代表從1970到2069的年份。70-99表示1970-1999;00-69表示2000-2069 MySQL以 YYYY 或YY 格式顯示YEAR 值,但允許分配使用字符串或數字將值添加到YEAR 列。 |
0000 |
對於timestamp
類型,服務器處理timestamp
定義的方式取決於explicit_defaults_for_timestamp
系統變量的值。
- 如果啓用了
explicit_defaults_for_timestamp
,則不會將DEFAULT CURRENT_TIMESTAMP
或ON UPDATE CURRENT_TIMESTAMP
屬性自動分配給任何TIMESTAMP
列。它們必須明確包含在列定義中。另外,任何未明確聲明爲NOT NULL
的TIMESTAMP
都允許NULL
值。 - 如果禁用
explicit_defaults_for_timestamp
,則服務器按以下方式處理TIMESTAMP
:- 沒有特別指定的情況下,
insert
、update
操作時,表中的第一個timestamp
列的值會被自動更新成當前時間(如果沒有指定值,或者指定NULL
),其他timestamp
列如果設置了NOT NULL
,而傳入NULL
時,也會被更新成當前時間 - 可以使用
DEFAULT CURRENT_TIMESTAMP
和ON UPDATE CURRENT_TIMESTAMP
列定義子句來指定自動初始化和更新到當前日期和時間。默認情況下,第一個TIMESTAMP
列具有這些屬性。但是,可以將表中的任何TIMESTAMP
列定義爲具有這些屬性。
- 沒有特別指定的情況下,
從MySQL 5.6.6開始,explicit_defaults_for_timestamp
可用。在5.6.6之前,服務器將處理TIMESTAMP
,如禁用explicit_defaults_for_timestamp
情況所述。
查看explicit_defaults_for_timestamp
是否啓用
show variables like 'explicit_defaults_for_timestamp';
string (character and byte) types
用於表示字符串(字符和字節)類型的數據類型有: CHAR
、VARCHAR
、 BINARY
、 VARBINARY
、 BLOB
、TEXT
、ENUM
、SET
。.
對於字符串列(CHAR
,VARCHAR
和TEXT
類型)的定義,MySQL以字符單位解釋長度規範。對於二進制字符串列(BINARY
,VARBINARY
和BLOB
類型)的定義,MySQL以字節單位解釋長度規範
[NATIONAL] CHAR[(M)]
- 固定長度的字符串,在存儲時總是用空格填充到指定的長度。
M
代表以字符爲單位的列長。M
的範圍是0到255。如果省略M
,則長度是1 - 除非啓用了
PAD_CHAR_TO_FULL_LENGTH
SQL模式,否則在檢索CHAR
值時將刪除尾部空格 NATIONAL CHAR
(或其等效的簡短格式NCHAR
)是定義CHAR
列應使用一些預定義字符集的標準SQL方法。 MySQL使用utf8
作爲此預定義字符集
- 固定長度的字符串,在存儲時總是用空格填充到指定的長度。
[NATIONAL] VARCHAR(M)
- 可變長度的字符串。
M
表示最大列長度,以字符爲單位。M
的範圍是0到65535 VARCHAR
的有效最大長度取決於最大行大小(65535字節,這個值在所有列之間共享)和所使用的字符集。例如,utf8
字符每個字符最多需要三個字節,因此使用utf8
字符集的VARCHAR
列可以聲明爲最多21844個字符- MySQL存儲
varchar
類型的數據時,需要1個字節或者2個字節作爲數據的前綴,如果值的長度不超過255個字節,使用1個字節,如果有可能超過255個字節,則使用2個字節 - MySQL不會從
VARCHAR
值中刪除尾部空格 NATIONAL VARCHAR
是定義VARCHAR
列應使用某些預定義字符集的標準SQL方法。 MySQL使用utf8
作爲此預定義字符集。NVARCHAR
是NATIONAL VARCHAR
的簡寫
- 可變長度的字符串。
最佳實踐
數值類型
- 應該儘量使用可以正確存儲數據的最小數據類型,更小的數據類型通常更快,因爲它們佔用更少的磁盤、內存和CPU緩存,並且處理時需要的CPU週期更少,但是要確保沒有低估需要存儲的值的範圍,如果無法確認哪個數據類型,就選擇你認爲不會超過範圍的最小類型
- 儘量使用簡單的數據類型,簡單數據類型的操作通常需要更少的CPU週期,例如,
- 整型比字符操作代價更低,因爲字符集和校對規則是字符比較比整型比較更復雜,
- 使用mysql自建類型,而不是字符串來存儲日期和時間
- 可以考慮用整型存儲IP地址
日期和時間類型
日期類型的選取,最麻煩的地方在於datetime
和timestamp
這兩個類型的選取。所以必須完全瞭解這兩種類型的區別,再結合實際情況進行取捨。
datetime
和timestamp
區別
- 存儲:
datetime
佔8個字節,timestamp
佔4個字節 - 範圍:
datetime
表示區間[1000-01-01 00:00:00, 9999-12-31 23:59:59],timestamp
表示區間[1970-01-01 , 2038-01-19] - 時區:
datetime
值不隨時區變化而變化,timestamp
一旦時區變動,會自動修改timestamp
的值 - 效率:
timestamp
更輕量,索引起來更快
瞭解了這幾點區別之後,相信比較容易就能做出取捨了。
字符串類型
字符串類型的選取,基本上也就糾結於char
和varchar
,所以需要了解兩者的具體區別
- 長度:
char
最長255個字符,varchar
最長約21844個字符 - 檢索:
char
檢索時會自動去除尾部空格,varchar
不會 - 效率:
char
寫效率比varchar
高,以空間換時間
參考
- https://dev.mysql.com/doc/refman/5.6/en/data-types.html