兩個重要概念
1.對於mysql來說,一條sql中,一個表無論其蘊含的索引有多少,但是有且只用一條。
2.對於多列索引來說(a,b,c)其相當於3個索引(a),(a,b),(a,b,c)3個索引,又由於mysql的索引優化器,其where條件后的語句是可以亂序的,比如(b,c,a)也是可以用到索引。如果條件中a,c出現的多,為了更好的利用索引故最好將其修改為(a.c,b)。
ICP概念
看了一篇大神的博客,上面說了通用索引匹配原則,這里也順便說下。
1.Index range 先確認索引的起止范圍。
2.Index Filter 索引過濾。
3.Table Filter 表過濾。
傳說中mysql5.6后提出的icp就是多了第二步,以前Index filter是放在數據上操作的,現在5.6后多了第二步,因此效率提高了很多。
原則:
1、需要加索引的字段,要在where條件中
2、數據量少的字段不需要加索引
3、如果where條件中是OR關系,加索引不起作用
4、符合最左原則
舉例:
聯合索引(a、b、c) 使用a或者a或者a、b或a、b、c這3種可以進行查找,不支持b、c進行查找
什么時候創建組合索引?
當我們的where查詢存在多個條件查詢的時候,我們需要對查詢的列創建組合索引
為什么不對沒一列創建索引
- 減少開銷
- 覆蓋索引
- 效率高
減少開銷:假如對col1、col2、col3創建組合索引,相當於創建了(col1)、(col1,col2)、(col1,col2,col3)3個索引
覆蓋索引:假如查詢SELECT col1, col2, col3 FROM 表名,由於查詢的字段存在索引頁中,那么可以從索引中直接獲取,而不需要回表查詢
效率高:對col1、col2、col3三列分別創建索引,MySQL只會選擇辨識度高的一列作為索引。假設有100w的數據,一個索引篩選出10%的數據,那么可以篩選出10w的數據;對於組合索引而言,可以篩選出100w*10%*10%*10%=1000條數據。
最左匹配原則
假設我們創建(col1,col2,col3)這樣的一個組合索引,那么相當於對col1列進行排序,也就是我們創建組合索引,以最左邊的為准,只要查詢條件中帶有最左邊的列,那么查詢就會使用到索引。
最頻繁使用的列放在左邊;查看列的選擇性(即該列的索引值數量與記錄數量的比值),比值越高,效果越好;
表的結構
CREATE TABLE `left_test` (
`id` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
`e` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `m_index` (`a`,`b`,`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
且插入了100萬條數據。
sql的分析
select * from left_table where id=1。
select * from left_table where id>1 and id<3
使用了聚集索引,id為主鍵,那么這個表里面id則是聚集索引列,這條sql默認使用了聚集索引來搜索。
select * from left_table where a=1
select * from left_table where a=1 and b=1
select * from left_table where a=1 and b=1 and c=1
使用聯合索引(a,b,c)。其中這些條件可以可以亂序,因為mysql的sql優化器會優化這些代碼
select * from left_table where a<1
select * from left_table where a<1 and b<1
select * from left_table where a<1 and b<1 and c<1
對於現在mysql5.7中,只有小於等於和小於才會觸發索引。而大於則是無法觸發索引,且小於可以亂序(mysql優化器優化了),但是按照最左匹配原則。比如條件(b),(c),(b,c)組合就不行。
