MySQL優化:數據類型

前言

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。顯示寬度與類型可以存儲的值的範圍無關

UNSIGNEDZEROFILL是兩個額外的屬性,分別表示:是否有符號是否填充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]的形式,看起來有點繞,實際上是存在三種寫法:typetype(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可用於與其他數據庫系統兼容。

浮點數

浮點數包括floatdouble兩種類型

數據類型 解釋
float[(M,D)] 單精度浮點數。M是總位數,D是小數點後的位數。如果省略MD,則將值存儲到硬件允許的極限。單精度浮點數的精度約爲小數點後7位
FLOAT(M,D)是非標準的MySQL擴展
float(p) 浮點數。 p表示位精度,但是MySQL僅使用此值來確定對結果數據類型使用FLOAT還是DOUBLE。如果p從0到24,則數據類型爲FLOAT,沒有MD值。如果p爲25到53,則數據類型將變爲DOUBLE,且沒有MD值。
FLOAT(p)語法以實現ODBC兼容性
double[(M,D)] / double precision[(M,D)] / real[(M,D)] 雙精度浮點數。M是總位數,D是小數點後的位數。如果省略MD,則將值存儲到硬件允許的極限。雙精度浮點數精確到大約15個小數位
DOUBLE(M,D)是非標準的MySQL擴展
如果啓用REAL_AS_FLOAT SQL模式,則REALFLOAT的同義詞,而不是DOUBLE

date and time types

用於表示時間值的日期和時間數據類型爲DATETIMEDATETIMETIMESTAMPYEAR

類型 解釋 零值
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以YYYYYY格式顯示YEAR值,但允許分配使用字符串或數字將值添加到YEAR列。
0000

對於timestamp類型,服務器處理timestamp定義的方式取決於explicit_defaults_for_timestamp系統變量的值。

  • 如果啓用了explicit_defaults_for_timestamp,則不會將DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP屬性自動分配給任何TIMESTAMP列。它們必須明確包含在列定義中。另外,任何未明確聲明爲NOT NULLTIMESTAMP都允許NULL值。
  • 如果禁用explicit_defaults_for_timestamp,則服務器按以下方式處理TIMESTAMP
    • 沒有特別指定的情況下,insertupdate操作時,表中的第一個timestamp的值會被自動更新成當前時間(如果沒有指定值,或者指定NULL),其他timestamp列如果設置了NOT NULL,而傳入NULL時,也會被更新成當前時間
    • 可以使用DEFAULT CURRENT_TIMESTAMPON 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

用於表示字符串(字符和字節)類型的數據類型有: CHARVARCHARBINARYVARBINARYBLOBTEXTENUMSET。.

對於字符串列CHARVARCHARTEXT類型)的定義,MySQL以字符單位解釋長度規範。對於二進制字符串列BINARYVARBINARYBLOB類型)的定義,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作爲此預定義字符集。NVARCHARNATIONAL VARCHAR的簡寫

最佳實踐

數值類型

  • 應該儘量使用可以正確存儲數據的最小數據類型,更小的數據類型通常更快,因爲它們佔用更少的磁盤、內存和CPU緩存,並且處理時需要的CPU週期更少,但是要確保沒有低估需要存儲的值的範圍,如果無法確認哪個數據類型,就選擇你認爲不會超過範圍的最小類型
  • 儘量使用簡單的數據類型,簡單數據類型的操作通常需要更少的CPU週期,例如,
    • 整型比字符操作代價更低,因爲字符集和校對規則是字符比較比整型比較更復雜,
    • 使用mysql自建類型,而不是字符串來存儲日期和時間
    • 可以考慮用整型存儲IP地址

日期和時間類型

日期類型的選取,最麻煩的地方在於datetimetimestamp這兩個類型的選取。所以必須完全瞭解這兩種類型的區別,再結合實際情況進行取捨。
datetimetimestamp區別

  • 存儲: 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更輕量,索引起來更快

瞭解了這幾點區別之後,相信比較容易就能做出取捨了。

字符串類型

字符串類型的選取,基本上也就糾結於charvarchar,所以需要了解兩者的具體區別

  • 長度:char最長255個字符varchar最長約21844個字符
  • 檢索:char檢索時會自動去除尾部空格,varchar不會
  • 效率:char寫效率比varchar高,以空間換時間

參考

  • https://dev.mysql.com/doc/refman/5.6/en/data-types.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章