我說MySQL聯合索引遵循最左前綴匹配原則,面試官讓我回去等通知

面試官: 我看你的簡歷上寫着精通MySQL,問你個簡單的問題,MySQL聯合索引有什麼特性?

心想,這還不簡單,這不是問到我手心裏了嗎?

聽我給你背一遍八股文!

image

我: 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聯合索引可能有時候不遵循最左前綴匹配原則。

面試官: 什麼時候遵循?什麼時候不遵循?

我: 可能是晴天遵循,下雨了就不遵循了,每個月那幾天不舒服的時候也不遵循了……

面試官: 好吧,今天面試就到這了,你先回去等通知,有後續消息會聯繫你的。

我擦,這叫什麼問題啊?

什麼遵循不遵循?

難道是面試官跟我背的八股文不是同一套?

image

回去到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='一燈';

image

雖然SQL查詢條件只有name字段,但是從執行計劃中看到依然是用了聯合索引。

並且Extra列中顯示增加了Using index for skip scan,表示用到了索引跳躍掃描的優化邏輯。

具體優化方式,就是匹配的時候遇到第一列索引就跳過,直接匹配第二列索引的值,這樣就可以用到聯合索引了。

其實我們優化一下SQL,把第一列的所有枚舉值加到where條件中,也可以用到聯合索引:

select * from user where gender in (0,1) and name='一燈';

看來還是需要經常更新自己的知識體系,一不留神就out了!

image

你覺得呢?

文章持續更新,可以微信搜一搜「 一燈架構 」第一時間閱讀更多技術乾貨。