讀mysql文檔有感
看了mysql關於索引的文檔,網上有一些錯誤的博客文檔,這里我自己記一下。
幾個重要的概念
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后多了第二步,因此效率提高了很多。
表的結構
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)組合就不行。
select * from left_table where b<1 select * from left_table where b<1 and c<1 select * from left_table where c<1
這個組合就用不到索引,因為不符合最左匹配原則。
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這個版本,大於是不參與索引匹配的因此這些sql都沒參與索引匹配。
select * from left_table where a=1 and id=2
這里面id是聚簇索引列,而a是個二級索引列,那么這個是用聚集索引列,不用(a,b,c)這個索引,因為對於mysql 5.7 innodb 這個版本一條sql里面索引只能用一條。至於用那個,則是mysql自身的算法選擇了。經過大量測試實驗,規則如下,如果索引列數據數據一模一樣,那么是誰先創建就選誰,如不一樣,那么誰占用的列越多,或者列的數據越復雜則選它。