1. 認識聯合索引
聯合索引:是指對錶上的多個列進行索引。適合where條件中的多列組合,在某些場景可以避免回表。
如下圖所示:
在進行order by操作時,聯合索引的字段數量大於1,比如上圖就有a和b兩個字段,與單個字段的B+樹一樣,也是按照字段排序的。比如圖中a、b兩個字段的值都是(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),是按照(a,b)進行排序的。因此對於a、b兩個字段都作爲條件時,查詢是可以走索引的;對於單獨a字段查詢也是可以走索引的。但是對於b字段單獨查詢就走不了索引了,因爲b字段對應的值是1,2,3,1,2,3,顯然不是有序的,所以走不了b字段的索引。
所以當使用聯合索引的時候:
- 在where條件中,經常同時出現的列放在聯合索引中;
- 把選擇性最大的列放在聯合索引的最左邊;
2. 聯合索引使用分析
2.1 可以完整用到聯合索引的情況
- a、b、c爲一個聯合索引,因此當聯合索引各字段都作爲條件時
select * from t11 where a=1 and b=1 and c=1;
- 各字段的位置不會影響聯合索引的使用
select * from t11 where c=1 and b=1 and a=1;
- 當聯合索引前面的字段使用了範圍查詢,後面的字段作爲條件時仍然可以使用完整的聯合索引
select * from t11 where a=2 and b in (1,2) and c=2;
- 聯合索引前面的字段作爲條件時,對後面的字段做排序可以使用完整的聯合索引
select * from t11 where a=1 and b=2 order by c;
- 對聯合索引第一個字段做條件篩選時,對後面兩個字段做排序可以使用完整的聯合索引
select * from t11 where a=1 order by b,c;
- 對聯合索引的字段同時做排序時,排序的是三個字段要跟聯合索引中的三個字段完全一致,而且查詢出的字段只能是聯合索引中的字段,可以完整的用到聯合索引
2.2 只能使用部分聯合索引的情況
- 當條件只包含聯合索引的前面部分字段時,可以用到部分聯合索引
select * from t11 where a=1 and b=1;
- 對於聯合索引a,b,c,如果條件中只包含a和c,則只能用到聯合索引中a的索引。c這裏是用不了索引的。聯合索引a、b、c相當於單個索引a、聯合索引a、b,聯合索引a、b、c三種索引,稱爲聯合索引的最左原則。
select * from t11 where a=1 and c=1;
- 當聯合索引前面的字段使用了範圍查詢,對後面的字段排序使用不了索引排序,也就是說只能用到聯合索引的前面兩個字段a和b的索引
2.3 可以用到覆蓋索引的情況
覆蓋索引就是從輔助索引中就可以查詢到結果,不需要回表查詢聚集索引中的記錄。通過覆蓋索引,不需要回表掃描聚集索引,因此可以減少SQL執行過程中的IO次數。
-
通過a字段上的條件,去聯合索引idx_a_b_c的索引樹上可以直接找到b字段和c字段的值,不需要回表,因此下面的SQL語句使用了覆蓋索引
select b,c from t11 where a=3;
-
通過a和b字段的值可以字節找到c的值,因此下面SQL語句使用了覆蓋索引
select c from t11 where a=1 and b=1 ;
-
通過a、b、c三個字段的值,去聯合索引樹中的葉子節點找到主鍵id,不需要回表,因此下面SQL語句使用了覆蓋索引
select id from t11 where a=1 and b=1 and c=1;
2.4 不能使用聯合索引的情況
-
如果只使用聯合索引後面的字段作爲條件查詢,則使用不了聯合索引,因爲聯合索引的最左匹配原則,如果第一個字段在條件中沒有出現,那麼聯合索引的後面所有字段作爲條件都無法使用這個聯合索引
select * from t11 where b=1;
-
對聯合索引後面的字段做排序操作,也使用不了聯合索引
select * from t11 where c=1;