比較簡單的是單列索引(b+tree)。遇到多條件查詢時,不可避免會使用到多列索引。聯合索引又叫復合索引。
b+tree結構如下:
每一個磁盤塊在mysql中是一個頁,頁大小是固定的,mysql innodb的默認的頁大小是16k,每個索引會分配在頁上的數量是由字段的大小決定。當字段值的長度越長,每一頁上的數量就會越少,因此在一定數據量的情況下,索引的深度會越深,影響索引的查找效率。
對於復合索引(多列b+tree,使用多列值組合而成的b+tree索引)。遵循最左側原則,從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。例如索引是key index (a,b,c). 可以支持a a,b a,b,c 3種組合進行查找,但不支持 b,c進行查找。當使用最左側字段時,索引就十分有效。
創建表test如下:
create table test(
a int,
b int,
c int,
KEY a(a,b,c));
比如(a,b,c)的時候,b+數是按照從左到右的順序來建立搜索樹的,比如當(a=? and b=? and c=?)這樣的數據來檢索的時候,b+樹會優先比較a列來確定下一步的所搜方向,如果a列相同再依次比較b列和c列,最后得到檢索的數據;但當(b=? and c=?)這樣的沒有a列的數據來的時候,b+樹就不知道下一步該查哪個節點,因為建立搜索樹的時候a列就是第一個比較因子,必須要先根據a列來搜索才能知道下一步去哪里查詢。比如當(a=? and c=?)這樣的數據來檢索時,b+樹可以用a列來指定搜索方向,但下一個字段b列的缺失,所以只能把a列的數據找到,然后再匹配c列的數據了, 這個是非常重要的性質,即索引的最左匹配特性。以下通過例子分析索引的使用情況,以便於更好的理解聯合索引的查詢方式和使用范圍。
一、多列索引在and查詢中應用
select * from test where a=? and b=? and c=?;查詢效率最高,索引全覆蓋。 select * from test where a=? and b=?;索引覆蓋a和b。 select * from test where b=? and a=?;經過mysql的查詢分析器的優化,索引覆蓋a和b。 select * from test where a=?;索引覆蓋a。 select * from test where b=? and c=?;沒有a列,不走索引,索引失效。 select * from test where c=?;沒有a列,不走索引,索引失效。
二、多列索引在范圍查詢中應用
select * from test where a=? and b between ? and ? and c=?;索引覆蓋a和b,因b列是范圍查詢,因此c列不能走索引。 select * from test where a between ? and ? and b=?;a列走索引,因a列是范圍查詢,因此b列是無法使用索引。 select * from test where a between ? and ? and b between ? and ? and c=?;a列走索引,因a列是范圍查詢,b列是范圍查詢也不能使用索引。
三、多列索引在排序中應用
select * from test where a=? and b=? order by c;a、b、c三列全覆蓋索引,查詢效率最高。 select * from test where a=? and b between ? and ? order by c;a、b列使用索引查找,因b列是范圍查詢,因此c列不能使用索引,會出現file sort。
四,總結聯合索引的使用在寫where條件的順序無關,mysql查詢分析會進行優化而使用索引。但是減輕查詢分析器的壓力,最好和索引的從左到右的順序一致。使用等值查詢,多列同時查詢,索引會一直傳遞並生效。因此等值查詢效率最好。索引查找遵循最左側原則。但是遇到范圍查詢列之后的列索引失效。排序也能使用索引,合理使用索引排序,避免出現file sort。