mysql組合索引

定義

不同於對某列建立索引,可以同時對多個列建立索引,也稱複合索引、聯合索引。

測試表

CREATE TABLE `test` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `c1` int(10) NOT NULL COMMENT 'c1',
  `c2` int(10) NOT NULL COMMENT 'c2',
  `c3` int(10) NOT NULL COMMENT 'c3',
  `c4` int(10) NOT NULL COMMENT 'c4',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `IDX_C1C2C3` (`c1`,`c2`,`c3`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

其中對c1、c2、c3建立組合索引。

存儲結構

單索引的存儲結構很好理解,非葉子節點中存儲單索引的值。當有多個列組成組合索引時,存儲結構如圖,摘自《高性能Mysql,第三版》
摘自高性能mysql
組合索引對多個值進行排序是依照定義時索引的的順序。這裏按照c1、c2、c3的順序定義,即在存儲時先按照c1排序,c1相同時按c2進行排序,c2相同時按c3排序。所以查詢時想使索引中的c2列生效,那麼條件中也要有c1。想使c3列生效,c1和c2必須也要有。這也就是常說的組合索引最左前綴匹配

測試

  • 全匹配
EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c2 = 222 and c3 = 333

在這裏插入圖片描述
key_len爲12,正好爲三個字段的長度,證明三個字段的索引全部生效了。
where後的查詢順序不影響組合索引的使用

EXPLAIN SELECT  * FROM test WHERE c2 = 222 and c1 = 111 and c3 = 333

只要包含了需要的索引,explain的結果和上面的一樣,不再貼出。

  • 不含c1
EXPLAIN SELECT  * FROM test WHERE c2 = 222 and c3 = 333;

在這裏插入圖片描述
搜索條件不含c1,發現走的全表掃描,組合索引沒有生效。

  • 不含c2
EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c3 = 333

在這裏插入圖片描述
雖然用到了聯合索引,但是實際使用長度只有4,也就是隻用了c1。

  • 不含c3
EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c2 = 222

在這裏插入圖片描述
使用了聯合索引,實際使用長度爲8,c1和c2都用上了。

  • 匹配列
    這裏把c2改成varchar(10)
EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c2 LIKE '22' and c3 = 333

在這裏插入圖片描述
key_len爲40,c1、c2、c3全部使用了。

EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c2 LIKE '%22' and c3 = 333

在這裏插入圖片描述
key_len爲4,只用到了c1。結合組合索引的存儲也可以理解,匹配前綴的時候,可以用到排序,但是匹配後綴,排序就失效了,所以從c2這裏就斷掉了。

  • 匹配範圍值
EXPLAIN SELECT  * FROM test WHERE c1 = 111 and c2 < 22 and c3 = 33

在這裏插入圖片描述
key_len爲8,c1和c2生效,範圍搜索後的c3失效了。

  • 其他失效情況
EXPLAIN SELECT  * FROM test WHERE c1  = 111 and c2 + 2 = 22 and c3 = 33

在這裏插入圖片描述
計算式會使該列索引失效,這裏只有c1生效了。

EXPLAIN SELECT  * FROM test WHERE c1  = 111 and c2 != 22 and c3 = 33

在這裏插入圖片描述
!=使得整個組合索引失效。

再次將c2改爲varchar(10)

EXPLAIN SELECT  * FROM test WHERE c1  = 111 and c2 not like '22' and c3 = 33

在這裏插入圖片描述
只有c1生效了。

EXPLAIN SELECT  * FROM test WHERE c1  = 111 and UPPER(c2) = '222' and c3 = 33

在這裏插入圖片描述
只有c1生效了。

參考

  1. 《高性能mysql,第三版》
  2. http://blog.codinglabs.org/articles/theory-of-mysql-index.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章