創建表
create table test( a int , b int, c int, d int, key index_abc(a,b,c) )engine=InnoDB default charset=utf8;
插入 10000 條數據
DROP PROCEDURE IF EXISTS proc_initData; DELIMITER $ CREATE PROCEDURE proc_initData() BEGIN DECLARE i INT DEFAULT 1; WHILE i<=10000 DO INSERT INTO test(a,b,c,d) VALUES(i,i,i,i); SET i = i+1; END WHILE; END $ CALL proc_initData();
建立了聯合索引(a,b,c)
驗證:
explain 指令詳解可以查看
explain select * from test where a<10 ; explain select * from test where a<10 and b <10; explain select * from test where a<10 and b <10 and c<10;
能不能將 a,b出現順序換一下,a,b,c出現順序換一下
explain select * from test where b<10 and a <10; explain select * from test where b<10 and a <10 and c<10;
不是最左匹配原則嗎?
查了下資料發現:mysql查詢優化器會判斷糾正這條sql語句該以什么樣的順序執行效率最高,最后才生成真正的執行計划。所以,當然是我們能盡量的利用到索引時的查詢順序效率最高咯,所以mysql查詢優化器會最終以這種順序進行查詢執行。
重點來了
explain select * from test where b<10 and c <10; explain select * from test where a<10 and c <10;
為什么 b<10 and c <10,沒有用到索引?而 a<10 and c <10用到了?
當b+樹的數據項是復合的數據結構,比如(name,age,sex)的時候,b+數是按照從左到右的順序來建立搜索樹的,比如當(張三,20,F)這樣的數據來檢索的時候,b+樹會優先比較name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最后得到檢索的數據;但當(20,F)這樣的沒有name的數據來的時候,b+樹就不知道下一步該查哪個節點,因為建立搜索樹的時候name就是第一個比較因子,必須要先根據name來搜索才能知道下一步去哪里查詢。比如當(張三,F)這樣的數據來檢索時,b+樹可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等於張三的數據都找到,然后再匹配性別是F的數據了, 這個是非常重要的性質,即索引的最左匹配特性。