天天看點

聯合索引使用規則

問題:

假設某個表有一個聯合索引(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了,看下面的結果:

聯合索引使用規則