面試官:我看你的簡歷上寫著精通MySQL,問你個簡單的問題,MySQL聯合索引有什麼特性? 我:MySQL聯合索引遵循最左首碼匹配原則,即最左優先,查詢的時候會優先匹配最左邊的索引。 例如當我們在(a,b,c)三個欄位上創建聯合索引時,實際上是創建了三個索引,分別是(a)、(a,b)、(a,b,c)... ...
面試官: 我看你的簡歷上寫著精通MySQL,問你個簡單的問題,MySQL聯合索引有什麼特性?
心想,這還不簡單,這不是問到我手心裡了嗎?
聽我給你背一遍八股文!
我: MySQL聯合索引遵循最左首碼匹配原則,即最左優先,查詢的時候會優先匹配最左邊的索引。
例如當我們在(a,b,c)三個欄位上創建聯合索引時,實際上是創建了三個索引,分別是(a)、(a,b)、(a,b,c)。
查詢條件中包含這些索引的時候,查詢就會用到索引。例如下麵的查詢條件,就可以用到索引:
select * from table_name where a=?;
select * from table_name where a=? and b=?;
select * from table_name where a=? and b=? and c=?;
其他查詢條件不包含這些索引的查詢語句,就不會用到索引,例如:
select * from table_name where b=?;
select * from table_name where c=?;
select * from table_name where b=? and c=?;
如果查詢條件包含(a,c),也會用到索引,相當於用到了(a)索引。
面試官: 小伙子,你的八股文背的挺熟啊。
我: 也沒有辣,我只是平常熱愛學習知識,經常做一些總結彙總,所以就脫口而出了。
面試官: 別開染坊了,我再問你,MySQL聯合索引一定遵循最左首碼匹配原則嗎?
我擦,這把我問的不自信了。
我: 嗯……,MySQL聯合索引可能有時候不遵循最左首碼匹配原則。
面試官: 什麼時候遵循?什麼時候不遵循?
我: 可能是晴天遵循,下雨了就不遵循了,每個月那幾天不舒服的時候也不遵循了……
面試官: 好吧,今天面試就到這了,你先回去等通知,有後續消息會聯繫你的。
我擦,這叫什麼問題啊?
什麼遵循不遵循?
難道是面試官跟我背的八股文不是同一套?
回去到MySQL官網上翻了一下,才發現面試官想問的是索引跳躍掃描(Index Skip Scan)。
MySQL8.0版本開始增加了索引跳躍掃描的功能,當第一列索引的唯一值較少時,即使where條件沒有第一列索引,查詢的時候也可以用到聯合索引。
造點數據驗證一下,先創建一張用戶表:
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵',
`name` varchar(255) NOT NULL COMMENT '姓名',
`gender` tinyint NOT NULL COMMENT '性別',
PRIMARY KEY (`id`),
KEY `idx_gender_name` (`gender`,`name`)
) ENGINE=InnoDB COMMENT='用戶表';
在性別和姓名兩個欄位上(gender
,name
)建立聯合索引,性別欄位只有兩個枚舉值。
執行SQL查詢驗證一下:
explain select * from user where name='一燈';
雖然SQL查詢條件只有name欄位,但是從執行計劃中看到依然是用了聯合索引。
並且Extra列中顯示增加了Using index for skip scan,表示用到了索引跳躍掃描的優化邏輯。
具體優化方式,就是匹配的時候遇到第一列索引就跳過,直接匹配第二列索引的值,這樣就可以用到聯合索引了。
其實我們優化一下SQL,把第一列的所有枚舉值加到where條件中,也可以用到聯合索引:
select * from user where gender in (0,1) and name='一燈';
看來還是需要經常更新自己的知識體系,一不留神就out了!
你覺得呢?
文章持續更新,可以微信搜一搜「 一燈架構 」第一時間閱讀更多技術乾貨。