===============
1 准備數據
1.1 建表
DROP TABLE IF EXISTS test03; CREATE TABLE test03 ( id INT PRIMARY KEY auto_increment, c1 char(10), c2 char(10), c3 char(10), c4 char(10), c5 char(10) );
1.2 插入數據
INSERT INTO test03(c1, c2, c3, c4, c5) VALUES('a1', 'a2', 'a3', 'a4', 'a5'); INSERT INTO test03(c1, c2, c3, c4, c5) VALUES('b1', 'b2', 'b3', 'b4', 'b5'); INSERT INTO test03(c1, c2, c3, c4, c5) VALUES('c1', 'c2', 'c3', 'c4', 'c5'); INSERT INTO test03(c1, c2, c3, c4, c5) VALUES('d1', 'd2', 'd3', 'd4', 'd5');
2 測試&Explain分析
2.1 建立索引
CREATE INDEX idx_c1234 ON test03(c1, c2, c3, c4);
2.2 測試
Case#1:用到一個索引(注意:key_len=31)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1';

Case#2:用到兩個索引(注意:key_len=62)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2';

Case#3:用到三個索引(注意:key_len=93)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c3 = 'a3';

Case#4:用到四個索引(注意:key_len=124)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c3 = 'a3' AND c4 = 'a4';

Case#5:用到四個索引(注意:這里的查詢條件順序是 1 2 4 3 而不是 1 2 3 4)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c4 = 'a4' AND c3 = 'a3';

Case#6:用到四個索引(這里的順序是 4 3 2 1)
EXPLAIN SELECT * FROM test03 WHERE c4 = 'a4' AND c3 = 'a3' AND c2 = 'a2' AND c1 = 'a1';

Case#7:用到了三個索引(注意:第三個查詢條件是大於)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c3 > 'a3' AND c4 = 'a4';

結果:
- key_len=93
- type=range
- ref=Null
- 由以上三點可推知:使用了三個索引(使用到了 1 2 3 三個索引;由於范圍之后全失效,所以第四個索引沒有被使用到)
Case#8:用到了四個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c4 > 'a4' AND c3 = 'a3';

結果:
- key_len=124
- type=range
- ref=Null
- 使用到了四個索引
分析:Mysql很聰明,查詢優化器會分析,得出 1 2 3 是常量,4 是范圍查詢的結論,於是,四個索引都能被使用,且 type=range。
Case#9:用到了 1 2 兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' ORDER BY c3;

說明:索引有兩個功能(查找和排序),所以這里的 c3 實際上還是使用上了索引的,只是它的用處是在排序(而不是查找;對比 Case#11 的結果更容易理解)。
Case#10:用到了 1 2 兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c4 = 'a4' ORDER BY c3;

Case#11:用到了 1 2 兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' ORDER BY c4;

結果:key_len=62 說明確實用到了兩個索引,但是,由於建立的索引是 1 2 3 4 而此Sql是查詢 1 2 然后按照 4 來排序(中間斷掉了 3),於是出現了 Using filesort!對比 Case#9 的結果,它的Sql是查詢 1 2 然后按照 3 來排序,所以沒有出現 Using filesort。
Case#12:用到了一個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c5 = 'a5' ORDER BY c2, c3;

說明:這里只用到了 c1 一個索引,同時 c2 c3 用於排序,沒有出現 Using filesort(可以和 Case#11 進行對比)。
Case#13:用到了一個索引(注意:ORDER BY 后面是 c3 在前,c2 在后)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c5 = 'a5' ORDER BY c3, c2;

說明:用到了 c1 一個索引,但是之后的ORDER BY 是 c3 在前,c2 在后,這就相當於是直接 ORDER BY c3,於是,中間 c2 斷掉了,出現 Using filesort!此 Case 和 Case#11 效果差不多,都是索引中斷了一個中間兄弟。
Case#14:用到了兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' ORDER BY c2, c3;

說明:查詢字段是 1 2 而排序字段是 2 3,是連續的。
Case#15:用到了兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c5 = 'a5' ORDER BY c2, c3;

說明:比 Case#14 多了一個 c5 的查詢字段,但是對結果無影響。
Case#16:用到了兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 = 'a2' AND c5 = 'a5' ORDER BY c3, c2;

說明:ORDER BY c3, c2 居然沒有出現 Using filesort!
原因是:在 WHERE 中,c2 = 'a2' 已經是個常量了,所以 ORDER BY c3, c2 就直接等價於(簡化為)ORDER BY c3,故不會出現 Using filesort。
可以和 Case#13 進行對比,此例和 Case#13 的區別就是在於,多了一個 c2 = 'a2',這就把 c1 c2 c3 給連續起來了,沒有斷掉,故不會出現 Using filesort。
Case#17:用到了一個索引(注意:此例是 GROUP BY)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' GROUP BY c2, c3;

說明:分組必排序,所以 GROUP BY c2, c3 等價於 ORDER BY c2, c3,同時,WHERE 條件中有 c1,所以索引連續,能夠正常被使用上。
Case#18:用到了一個索引(注意:GROUP BY 中的 c3 在前,c2 在后)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' GROUP BY c3, c2;

說明:
- 能夠用到 c1 這個索引
- GROUP BY c3, c2 等價於 ORDER BY c3, c2,而之前只有 c1 於是索引斷掉了,所以出現 Using filesort(九死一生)
- GROUP BY 還需要對結果進行分組,所以產生了 Using temporary(十死無生)
Case#19:用到了兩個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 > 'a2' AND c3 = 'a3';

結果:用到了兩個索引,且type=range
Case#20:用到了三個索引(注意:中間的 c2 是 LIKE 查詢,且%在右邊)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 LIKE 'a2%' AND c3 = 'a3';

結果:和 Case#19 不同的是,此例用到了三個索引,且 type=range,有點難以理解,,,,,,,,,,,,待以后再來補充吧,,TODO
Case#21:用到了一個索引(注意:中間的 c2 是 LIKE 查詢,且%在左邊)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 LIKE '%a2' AND c3 = 'a3';

說明:type=ref 且 key_len=31,只用到了一個索引。也能說明,Like 以 % 開頭時無法使用索引。
Case#22:用到了一個索引(注意:中間的 c2 是 LIKE 查詢,且%在兩邊)
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 LIKE '%a2%' AND c3 = 'a3';

說明:和 Case#21 相同,也只用到了一個索引。
Case#23:用到了三個索引
EXPLAIN SELECT * FROM test03 WHERE c1 = 'a1' AND c2 LIKE 'a2%a2%' AND c3 = 'a3';

說明:結果和 Case#20 相同
