《高效能MySQL》筆記——MySQL建表資料型別的選擇

且聽の風吟發表於2018-11-07

 

前段時間看了《高效能MySQL》中的選擇優化的資料型別,這裡主要是做一下筆記。

首先資料選擇有幾個簡單原則:

  • 更小的通常更好。一般情況下,應該儘量使用可以正確儲存資料的最小資料型別。例如只需要存 0~200,tinyint unsigned 更好。更小的資料型別通常更快,因為它們佔用更少的磁碟、記憶體和 CPU 快取,並且處理時需要的 CPU 週期也更少。
  • 簡單就好。簡單資料型別的操作通常需要更少的 CPU 週期。例如,整型比字元操作代價更低,因為字符集和校對規則(排序規則)使字元比較 比 整型比較更復雜。這裡有兩個例子:一個是應該使用 MySQL 內建的型別(date, time, datatime)而不是字串來儲存日期和時間,另一個是應該用無符號整型儲存 IP 地址。
  • 儘量避免NULL。通常情況下最好指定列為 NOT NULL,除非真的需要儲存 NULL 值。如果查詢中包含可為 NULL 的列,對 MySQL 來說更難優化,因為可為 NULL 的列使得索引、索引統計和值比較都更復雜。特別是計劃在列上建索引,就應該儘量避免設計成可為 NULL 的列。

整數型別:(tinyint,smallint,mediumint,int,bigint)

  儲存(位元組) 儲存(位) 有符號範圍 無符號範圍
TINYINT 1 8 -128 ~127 0~255
SMALLINT 2 16 -32768~32767 0~65535
MEDIUMINT 3 24 -8388608~8388607 0~16777215
INT 4 32 -2147483648~2147483647 0~4294967295
BIGINT 8 64 -2^63~2^63-1 0~2^64-1

 

  • 整數型別有可選的 unsigned 屬性,表示不允許負值,這大致可以使正數的上限提高一倍。主鍵自增 id 適合設定為 unsigned 屬性的 int 型別。
  • MySQL 可以為整數型別指定寬度,例如 int(11),對大多數應用這是沒有意義的:它不會限制值的合法範圍,只是規定了 MySQL 的一些互動工具(例如 MySQL 命令列客戶端)用來顯示字元的個數。對於儲存和計算來說,int(1) 和 int(20) 是相同的。

實數型別:(float,double,decimal)

  • float,double 屬於浮點型別(近似值)。decimal 屬於定點型別(精確值)。
  • MySQL 浮點型和定點型可以用型別名稱後加(M,D)來表示,M 表示該值的總共長度,D 表示小數點後面的長度。
  • float 使用 4 個位元組儲存;double 使用使用 8 個位元組儲存;decimal 則是將數字打包儲存到一個二進位制字串中(每 4 個位元組存 9 個數字)。例如,decimal(18, 9) 小數點兩邊將各儲存 9 個數字,一共使用 9 個位元組:小數點前的數字用 4 個位元組,小數點後的數字用 4 個位元組,小數點本身佔 1 個位元組。
  • 因為需要額外的空間和計算開銷,所以應該儘量只在對小數進行精確計算時才使用 decimal——例如儲存財務資料。但在資料量比較大的時候,可以考慮使用 bigint 代替 decimal ,將需要儲存的貨幣單位根據最小的位數乘以相應的倍數即可。

 

字串型別:

varchar 和 char 型別

  • varchar 型別用於儲存可變長字串,是最常見的字串資料型別。
  • varchar 需要使用 1 或 2 個額外位元組記錄字串長度:如果列的最大長度小於或等於 255 位元組,則只使用 1 個位元組表示,否則使用 2 個位元組。
  • char 型別是定長的:MySQL 總是根據定義的字串長度分配足夠的空間。
  • char 儲存會刪除儲存資料的末尾空格;varchar 不會。(準確來說是 MySQL 4.1 以後的版本 varchar 不會刪除儲存資料的末尾空格)

 

blob 和 text 型別

  • blob 和 text 都是為了儲存很大的資料而設計的字串資料型別,分別採用二進位制和字元方式儲存。
  • 與其它型別不同,MySQL 把每個 blob 和 text 值當作一個獨立的物件處理。
  • blob 和 text 家族之間僅有的不同是 blob 型別儲存的是二進位制資料,沒有排序規則或字符集,而 text 型別有字符集和排序規則。
  • memory 引擎不支援 blob 和 text 型別。

 

列舉(enum)型別

  • MySQL 在內部會將每個值在列表中的位置儲存為整數,並且在表的 .frm 檔案中儲存 “數字-字串” 對映關係的 “查詢表”。
  • 如果使用數字作為列舉常量,這種雙重性很容易導致混亂,例如 enum(`1`, `2`, `3`) 。建議儘量避免這麼做。
  • 列舉欄位是按照內部儲存的整數而不是定義的字串進行排序的。

日期和時間型別:

  • MySQL 能儲存的最小時間粒度為秒。
  • datetime 儲存範圍從 1001 年到 9999 年,精度為秒。與時區無關。使用 8 位元組的儲存空間。
  • timestamp 型別儲存了從 1970 年 1 月 1 日 午夜(格林尼治標準時間)以來的秒數,它和 unix 時間戳相同。使用 4 位元組的儲存空間,範圍從 1970 年到 2038 年。與時區有關。
  • MySQL 4.1 以及更新的版本按照 datetime 的方式格式化 timestamp 的值,這僅僅是顯示格式上的區別,timestamp 的儲存格式在各個版本都是一樣的。
  • 除了特殊行為之外,通常也應該儘量使用 timestamp ,因為它比 datetime 空間效率更高。有時候人們會將 unix 時間戳儲存為整數值,但這不會帶來任何收益。用整數儲存時間戳的格式通常不方便處理,所以我們不推薦這麼做。(對於這點很多公司專案中是用整數儲存,我也查了資料,使用整數的理由一般是日期比較,計算時整數更好處理)

 

相關文章