MySQL常用explain指令檢視SQL的執行計劃,如:
其中key_len清單示SQL使用的索引長度,機關為位元組,通常在不損失精确性的情況下,長度越短越好。
一般可以根據表定義大概計算出索引的最大可能長度,可用于判斷聯合索引的實際使用字段情況。
一、索引長度計算規則
1、一般地,key_len等于索引列類型位元組長度,例如tinyint類型為1位元組,int類型為4位元組,bigint為8位元組。
2、如果是字元串類型,還需要同時考慮字元集因素(latin1為1位元組/gbk為2位元組/utf8為3位元組/utf8mb4為4位元組),例如:CHAR(30) UTF8,則key_len至少是90位元組。
3、如果是日期時間型,還需要考慮精度值,在MySQL5.6.4版本之後,各個日期時間類型需要的存儲空間如下:
其中小數秒是什麼意思呢?
在MySQL5.6.4這個版本之後,TIME、DATETIME、TIMESTAMP這幾種類型添加了對毫秒、微秒的支援。由于毫秒、微秒都不到1秒,是以也被稱為小數秒,MySQL最多支援6位小數秒的精度,前三位辨別毫秒,後三位辨別微秒。
以datetime為例,一般情況下時間格式為YYYY-MM-DD HH:MM:SS,為了讓我們的datetime類型支援小數秒,可以這麼寫:
dateime(小數秒位數),其中小數秒位數可以在0、1、2、3、4、5、6中選擇。
比如DATETIME(0)表示精确到秒,DATETIME(3)表示精确到毫秒,DATETIME(5)表示精确到10微秒。如果你在選擇TIME、DATETIME、TIMESTAMP這幾種類型的時候添加了對小數秒的支援,那麼所需的存儲空間需要相應的擴大,保留不同的小數秒位數,那麼增加的存儲空間大小也不同,如下表:
是以,計算索引長度時,datetime類型下,如果不使用小數秒,則隻占用5個位元組長度,datetime相當于是datetime(0),僅占用5位元組空間,而datetime(1)或datetime(2)占用6位元組、datetime(3)或datetime(4)占用7位元組、datetime(5)或datetime(6)占用8位元組。
4、若該列類型定義時允許NULL,還需要再加1位元組。
5、若該列類型為變長類型,例如 VARCHAR(TEXT/BLOB不允許整列建立索引,如果建立部分索引也被視為動态列類型),還需要再加2位元組來存儲該變長列的實際長度。
首先,看看官方文檔對varchar類型存儲空間長度的說法。
即MySQL需要1 ~ 2個位元組來表示varchar字元串的長度。具體來說,如果字元串占用的位元組數在 0 ~255 之間,需1個位元組來表示,如果大于 255 個位元組,則需2個位元組來表示。
但在計算索引長度的時候,統一加2位元組存儲該變長列的實際長度,與是否超過255位元組無關。
測試如下:
二、案例
索引長度計算如下:
(varchar50*4+2變長+1空值)+(varchar10*4+2變長)+(datetime(3)5+2)+(varchar6*4+2變長)=203+42+7+26=278
由此可看出idx_test的所有字段都走了索引。
三、總結
MySQL在執行計劃中輸出key_len列主要是為了讓我們區分某個使用聯合索引的查詢具體用了幾個索引列。
因為聯合索引有最左字首的特性,如果聯合索引能全部使用上,則是聯合索引字段的索引長度之和,這樣就可以用來判定聯合索引是部分使用,還是全部使用。