mysql學習(9):聯合索引和多個單列索引的使用區別詳解

前言
爲了提高數據庫的查詢效率,建索引是最常用的手段。那麼問題來了,如果查詢條件爲2個及以上,我們是創建多個單列索引好呢,還是建一個聯合索引比較好?

正文
我們首先來建一張表,並且指定其中的3個字段(學號、姓名、電話)爲聯合索引:

CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`stu_id` varchar(20) DEFAULT NULL COMMENT '學號',
`name` varchar(30) DEFAULT NULL COMMENT '姓名',
`phone` varchar(30) DEFAULT NULL COMMENT '電話',
`address` varchar(30) DEFAULT NULL COMMENT '家庭住址',
PRIMARY KEY (`id`),
KEY `聯合索引` (`stu_id`,`name`,`phone`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='學生表';
1
2
3
4
5
6
7
8
9
接下來我們使用Explain查詢來查看接下來的SQL查詢語句的執行計劃,這次我們只關注key和key_len列。其中key列顯示MySQL實際決定使用的索引,如果沒有使用到索引則顯示NULL。key_len列顯示索引中使用的字節數。

一、聯合索引驗證
1、針對聯合索引中的字段分別進行單個查詢
1、針對索引字段stu_id進行查詢,結果聯合索引有效:

EXPLAIN
SELECT * from student where stu_id = '001';
1
2

2、針對索引字段name進行查詢,結果聯合索引無效:

EXPLAIN
SELECT * from student where name = '小明';
1
2

3、針對索引字段phone進行查詢,結果聯合索引無效:

EXPLAIN
SELECT * from student where phone = '123';
1
2


2、針對聯合索引中的字段進行兩兩組合查詢
1、對索引排列中的前兩個(stu_id、name)進行查詢,結果聯合索引有效:

EXPLAIN
SELECT * from student where stu_id = '001' AND name= '小明';
1
2

2、對索引排列中的第一個和第三個(stu_id、phone)進行查詢,結果聯合索引有效:(注意這裏 1,3  也是有效的)

EXPLAIN
SELECT * from student where stu_id = '004' AND phone = '14785454554';
1
2

3、在第2點的基礎上,調換一下stu_id、phone的位置,結果聯合索引仍有效( 即使換了順序也是有效)

EXPLAIN
SELECT * from student where phone = '14785454554' AND stu_id = '004';
1
2


4、對索引排列中的第二個和第三個(name、phone)進行查詢,結果聯合索引無效:

EXPLAIN
SELECT * from student where stu_id = '004' OR name = '小軍';
1
2


3、針對聯合索引中的字段進行全組合查詢
1、按照索引的定義順序進行查詢,結果聯合索引有效:

EXPLAIN
SELECT * from student where stu_id = '004' AND name = '小明' AND phone = '123';
1
2

2、打亂3個查詢條件的順序,結果聯合索引仍有效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' AND stu_id = '004';
1
2

3、如果where條件出現OR,結果聯合索引無效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' OR stu_id = '004';
1
2


二、多個單列索引驗證
1、聯合索引和單列索引同時存在
再分別對那3個字段建一個索引,同時保留聯合索引:

create index index_stu_id on student(stu_id);
create index index_name on student(name);
create index index_phone on student(phone);
1
2
3
1、再來查詢單個字段stu_id,結果顯示使用了聯合索引:

EXPLAIN
SELECT * from student where stu_id = '004';
1
2

2、再來查單個字段phone,結果使用了單例索引:

EXPLAIN
SELECT * from student where phone = '14785454554';
1
2

其實這裏涉及到了mysql優化器的優化策略,當有多種索引存在時,優化器會評估哪個條件的索引效率最高,它會選擇最佳的索引去使用。

2、只有單列索引
現在去掉聯合索引,只剩下3個單列索引,再來進行查詢

drop index 聯合索引 on student;
1
1、單個字段查詢,結果使用了對應字段的索引:

EXPLAIN
SELECT * from student where phone = '123';
1
2

2、多個字段查詢,結果使用的是優化器選擇出來的索引:

EXPLAIN
SELECT * from student where phone = '123' AND stu_id = '004';
1
2

3、多個字段查詢,where條件使用OR,結果索引失效:

EXPLAIN
SELECT * from student where phone = '123' AND name = '小明' OR stu_id = '004';
1
2


總結
利用聯合索引,我們可以縮小搜索的範圍。但是使用聯合索引不同於使用多個單獨的索引。聯合索引的結構其實與通訊錄類似,人的名字由姓氏和名字組成,通訊錄通常首先按照姓氏進行排序,然後按名字對有相同姓氏的人進行排序。如果我們知道姓氏,那麼通過通訊錄查找將會很有用;如果我們同時知道姓氏和名字,那麼查通訊錄會更加有效;但是如果我們只知道姓名,不知道姓氏,那麼通訊錄將沒有用處。

所以我們在創建聯合索引時,應該仔細考慮下列的順序。對索引中的所有列執行查詢,或者對前幾列進行查詢,聯合索引將會非常有效;但是僅對後面的任意列進行搜索時,聯合索引將沒有用處。

多個單列索引在多個條件查詢時,優化器會選擇最優索引策列,可能只會用到其中一個索引,也可能用到多個索引。但是多個單列索引底層會建立多個B樹索引,比較佔用空間,也會浪費一定的搜索效率,所以只要有多個條件的聯合查詢,最好時建立聯合索引。

最左前綴原則:
以索引定義的最左邊爲起點,任何連續的索引都能匹配上,
注:如果第一個字段是範圍查詢,則需要單獨建一個索引。
注:在創建聯合索引時,要根據業務的要求,where子句中使用最頻繁的一列放在最左邊。這樣的擴展性比較好,比如stu_id經常作爲查詢條件,而phone不常用,則需要把stu_id放在聯合索引的第一位,即最左邊。

同時存在聯合索引和單列索引(字段有重複)時,這時mysql查詢會怎麼使用索引呢?這個涉及到mysql本身的查詢優化器策略了,當一個表有多條索引可以走時,mysql會根據查詢語句的成本來選擇走哪條索引。

聯合索引的本質理解:
當創建了(a,b,c)這個聯合索引時,相當於創建了下面這3條索引:
(a)這個單列索引;
(a,b)這個聯合索引;
(a,b,c)這個聯合索引。
想要索引生效的話,只能使用a,ab,abc這3種查詢方式。上面我們測試過,ac組合也可以,但實際上只用到了a的索引,c並沒有用到。
————————————————
版權聲明:本文爲CSDN博主「name_s_Jimmy」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

參考:mysql學習(9):聯合索引和多個單列索引的使用區別詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章