聯合索引使用規則


問題:

假設某個表有一個聯合索引(c1,c2,c3,c4)以下只能使用該聯合索引的c1,c2,c3部分

A where c1=x and c2=x and c4>x and c3=x

B where c1=x and c2=x and c4=x order by c3

C where c1=x and c4= x group by c3,c2

D where c1=? and c5=? order by c2,c3

E where c1=? and c2=? and c5=? order by c2,c3

一、創建測試表和聯合索引

創建表t1,有c1到c5共5個字段,特別說明一下,字段類型都是定長char(1) 類型,並且非空,字符集是utf8(與計算索引使用字節數有關)。

create table t1(
c1 char(1) not null default '',
c2 char(1) not null default '',
c3 char(1) not null default '',
c4 char(1) not null default '',
c5 char(1) not null default ''
)engine myisam charset utf8;

 創建聯合索引:

alter table t1 add index c1234(c1,c2,c3,c4);

插入3條數據:

insert into t1 values('a','b','c','d','e'),('A','b','c','d','e'),('a','B','c','d','e');

 二、分析

1、A選項

    我們看解析A這條sql的結果,與索引有關的主要是possible_keys,key,key_len這三項,possible_keys是指可能會用到的索引,key是當前sql使用到的索引,key_len是索引的使用字節數。key的值是c1234表示聯合索引用上了,那是不是c1,c2,c3,c4全用上了咧,我們得從key_len分析一下。

    因為字段類型是char(1),字符集是utf8,所以每個字段的key_len 是 1*3=3,key_len現在等於12表示c1,c2,c3,c4這四個字段都用上了索引,(如果字段類型是null,那單個字段的索引字節數需要 +1,如果字段類型為非定長類型,比如varchar,那字節數需要再 +2,這里方便理解,統一定義成了定長char)

2、B選項

    我們看到key=c1234,表示B使用了聯合索引,key_len=6表示有兩個字段使用了索引,這兩個字段就是C1和c2,這個sql里面有一個order by c3,order by不能使用索引,但是卻利用了索引,為什么這么說咧,如果我們改成order by c5,看下面的:

    與上面的結果對比,發現在Extra中的值使用了Using filesort。Using filesort表示在索引之外,需要額外進行外部的排序動作。因為c5的順序是沒有規律的,所以需要對其進行一次排序,而在order by c3的時候,c3其實在索引表里面已經是排好序的了,不需要再排序,所以說其實他利用上了索引。

3、C選項

     key=c1234,表示B使用了聯合索引,key_len=3表示有1個字段使用了索引,這個字段就是C1,與B語句不一樣的是 Extra的值,C語句里面使用了臨時表(Using temporary) 和 排序(filesort),因為組合索引是需要按順序執行的,比如c1234組合索引,要想在c2上使用索引,必須先在c1上使用索引,要想在c3上使用索引,必須先在c2上使用索引,依此類推。回到B語句中,因為c2字段已經使用了索引,所以在order by c3的時候 c3其實在索引表里面已經是排好序的了,不需要建臨時表,不需要再排序,所以說其實他利用上了索引。
而C語句中,group by 的順序是先c3,再c2,在對c3進行group by的時候,c2字段上的索引並沒用使用,所以索引在這里就斷了,只用上了c1一個字段的索引。

如果group by 的順序改成c2,c3,會是什么樣?

從結果中看沒有用到臨時表和filesort,因為c2,c3在索引表中本身就是有序的。

4、D選項

    從結果中看到key=c1234,表示B使用了聯合索引,key_len=3表示有一個字段使用了索引,即C1字段。而c2,c3字段在order by中是順序執行,所以也利用了索引。這里沒有使用filesort就是因為c2,c3本身在索引表中就是有序的,所以不需要對其再排序。那如果反之,先按c3排序,再按c2排序,會是什么情況,看下面:

從結果中看到使用了filesort,這里就無法合理的使用索引了。舉個例子來說,好比中國下的省是有序的,如果按照先找國家再找省那自然是順序的,而如果反過來,先找省再找國家,那肯定是亂序的,自然也就不能利用索引了。

5、E選項

E語句c1和c2使用了索引,c3在order by中利用了索引。如果再反之,先按c3排序,再按c2排序會是什么情況?

order by c3,c2,按理說應該使用filesort,但從結果中看並沒有使用,這是為什么呢?注意仔細看查詢條件,c1='a' and c2='b',那么在所有查詢出來的行中,c2其實只有一個值,永遠等於'b',也就是說c2是一個常量,也就意味着order by c3,c2 相當於對c3和一個常量排序,可以寫成這樣order by c3,'b',所以order by c3,'b'說白了還是對c3進行排序,因為后面的‘b’永遠都是一樣的,他是一個常量,而常量對排序並沒有影響,可以忽略不計,因此這里並沒有使用filesort。

如果將條件c2='b'去掉,那自然就要用到filesort了,看下面的結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM