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

語言: CN / TW / HK

攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第6天,點選檢視活動詳情

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

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

聽我給你背一遍八股文!

一切都在掌握.jpeg

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

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

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

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

我擦,這叫什麼問題啊?

什麼遵循不遵循?

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

what.jpeg

回去到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-20220803213714714.png

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

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

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

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

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

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

學無止境.jpeg

你覺得呢?

image.png