MySql中的範圍查詢對組合索引使用的影響

不知道大家有沒有聽過這麼一個江湖傳言:
“如果組合索引中包含的列,有範圍查詢,那麼它之後的列將不會走索引”。

本着“先問是不是,再問爲什麼”的原則,我們搞個試驗。

首先準備一個表“goods_detail”,主要字段:

tenant_id、buss_day、goods_id

我們創建一個組合索引:

KEY `idx_tbg` (`tenant_id`,`buss_day`,`goods_id`)

查詢語句SQL1:

SELECT
	* 
FROM
	goods_detail 
WHERE
	tenant_id = '996' 
	AND buss_day BETWEEN "2020/1/1" AND "2020/1/6" 
	AND goods_id = '985';

執行計劃如下:
在這裏插入圖片描述

查詢語句SQL2:

SELECT
	* 
FROM
	goods_detail 
WHERE
	tenant_id = '996' 
	AND buss_day IN ( "2020/1/1", "2020/1/2", "2020/1/3", "2020/1/4", "2020/1/5", "2020/1/6" ) 
	AND goods_id = '985';

執行計劃如下:
在這裏插入圖片描述
從以上兩個執行計劃可以看出:buss_day使用in匹配比between匹配掃描的行數要低得多
原因就在於:SQL2的組合索引中goods_id列條件使用上了索引

爲何between不走索引,採用in後可以走索引

在探尋原因之前,需要先看下索引是如何在mysql中存儲的。
我們通常使用的innodb中,索引的數據結構是B+樹(樹高度低、效率高),有兩種索引:聚簇索引、二級索引
聚簇索引:所有完整的用戶記錄都存放在這個聚簇索引的葉子節點處,在InnoDB存儲引擎中,聚簇索引就是數據的存儲方式
二級索引:除聚簇索引之外的索引,由用戶自主創建,不包含完整的用戶記錄,只包含用戶設置的部分字段

聯合索引
用戶在創建二級索引時,可以選擇單個字段作爲索引,也可以選擇多個字段作爲索引。我們稱多個字段組成的索引爲組合索引(或聯合索引)

mysql在存儲聯合索引時:

  1. 先把各個記錄和頁按照從左往右第一列進行排序。
  2. 在記錄的前一列相同的情況下,採用下一列進行排序
  3. 依此類推

通過以上操作,保證了所有索引數據是按照索引列的值從小到大的順序排好序的。
當我們要查找匹配索引條件時,只需從左往右依次匹配。

分析下SQL1:
第一列:tenant_id 等值匹配,可以匹配到精確地索引
第二列:buss_day範圍匹配,匹配出來的buss_day具體有哪些,是不可以知的
第三列:由於匹配出來的buss_day不可知,goods_id無法走索引匹配

分析下SQL2:
第一列:tenant_id 等值匹配,可以匹配到精確地索引
第二列:buss_day等值匹配,匹配出來的buss_day是可知的
第三列:由於匹配出來的buss_day可知,goods_id走索引匹配

在組合索引中,除了使用了between匹配外,採用>、<、like等進行匹配都會導致後面的列無法走索引,因爲通過以上方式匹配到的數據是不可知的。

歡迎拍磚。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章