我說MySQL聯合索引遵循最左字首匹配原則,面試官讓我回去等通知
攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第6天,點選檢視活動詳情
面試官: 我看你的簡歷上寫著精通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了!
你覺得呢?