MySQL最左匹配原則深入分析
前言
接下來我們通過幾種情況來描述最左匹配原則的使用。首先如下所示,為userName、phone以及userDate創(chuàng)建聯(lián)合索引。

全列匹配
explain select * from user where userName ='admin' and phone ='13413413400' and userDate ='2000-04-29-12:53'

很明顯,當(dāng)按照索引中所有列進(jìn)行精確匹配(這里精確匹配指“=”或“IN”匹配)時,索引可以被用到。這里有一點需要注意,理論上索引對順序是敏感的,但是由于MySQL的查詢優(yōu)化器會自動調(diào)整where子句的條件順序以使用適合的索引,例如我們將where中的條件順序顛倒,其效果是一樣的。
explain select * from user where userName ='admin' and userDate ='2000-04-29-12:53' and phone ='13413413400'

最左前綴匹配
比如我們where條件中只有userName:
explain select * from user where userName ='admin'

當(dāng)查詢條件精確匹配索引的左邊連續(xù)一個或幾個列時,如userName,索引可以被用
到,但是只能用到一部分,即條件所組成的最左前綴。
上面的查詢從分析結(jié)果看用到了 const 索引,key_len為152,說明只用到了索引的第一列前綴。
精確匹配
查詢條件用到了索引中列的精確匹配,但是中間某個條件未提供
比如下面我們沒有phone:
explain select * from user where userName ='admin' and userDate ='2000-04-29-12:53'

注意,上圖Extra中值是Using index condition,說明MySQL正在使用覆蓋索引,它只掃描索引的數(shù)據(jù)而不是按索引次序的每一行。它比按索引次序全表掃描的開銷要少很多。
此時索引使用情況和情況二相同,因為phone未提供,所以查詢只用到了索引的第一列,而后面的userDate雖然也在索引中,但是由于phone不存在而無法和左前綴連接,因此需要對結(jié)果進(jìn)行掃描過濾userDate。
如果想讓userDate也使用索引而不是where過濾,可以增加一個輔助索引<userName, userDate>,此時上面的查詢會使用這個索引。
查詢條件沒有指定索引第一列
由于不是最左前綴,索引這樣的查詢顯然用不到索引。
explain select * from user where userDate ='2000-04-29-12:53'

Using where:使用了用where子句來過濾結(jié)果集。這意味著MySQL服務(wù)器將在存儲引擎檢索行后再進(jìn)行過濾。
匹配某列的前綴字符串
explain select * from user where userName ='admin' and phone like '134%' and userDate ='2000-04-29-12:53'

此時可以用到索引,如果通配符%不出現(xiàn)在開頭,則可以用到索引,但根據(jù)具體情況不同可能只會用其中一個前綴。
范圍查詢
explain select * from user where userName ='admin' and phone >'134' and userDate ='2000-04-29-12:53'

范圍列可以用到索引(必須是最左前綴),但是范圍列后面的列無法用到索引。同時,索引最多用于一個范圍列,因此如果查詢條件中有兩個范圍列則無法全用到索引。
這里特別要說明MySQL一個有意思的地方,那就是僅用explain可能無法區(qū)分范圍索引和多值匹配,因為在type中這兩者都顯示為range。同時,用了“between”并不意味著就是范圍查詢,例如下面的查詢:
explain select * from user where userName ='admin' and phone between '13413413400' and '13513513500' and userDate ='2000-04-29-12:53'

看起來是用了兩個范圍查詢,但作用于phone上的“BETWEEN”實際上相當(dāng)于“IN”,也就是說phone實際是多值精確匹配。可以看到這個查詢用到了索引全部三個列。因此在MySQL中要謹(jǐn)慎地區(qū)分多值匹配和范圍匹配,否則會對MySQL的行為產(chǎn)生困惑。
查詢條件中含有函數(shù)或表達(dá)式
如果查詢條件中含有函數(shù)或表達(dá)式,則MySQL不會為這列使用索引。
explain select * from user where userName ='admin' and left(phone ,6) and userDate ='2000-04-29-12:53'

可以看到這個其實就是只用到了userName這一列的索引。
關(guān)于explain中各個關(guān)鍵字說明可以參考:認(rèn)真學(xué)習(xí)傳送門
到此這篇關(guān)于MySQL最左匹配原則深入分析的文章就介紹到這了,更多相關(guān)MySQL最左匹配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
讓MySQL數(shù)據(jù)庫跑的更快 為數(shù)據(jù)減肥
在MySQL數(shù)據(jù)庫優(yōu)化工作中,使數(shù)據(jù)盡可能的小,使表在硬盤上占據(jù)的空間盡可能的小,這是最常用、也是最有效的手段之一。2011-03-03
mysql-8.0.30壓縮包版安裝和配置MySQL環(huán)境過程
該文章介紹了如何在Windows系統(tǒng)中下載、安裝和配置MySQL數(shù)據(jù)庫,包括下載地址、解壓文件、創(chuàng)建和配置my.ini文件、設(shè)置環(huán)境變量、初始化MySQL服務(wù)、啟動服務(wù)以及修改root用戶密碼等步驟2025-01-01
Mysql插入帶有引號的字符串?dāng)?shù)據(jù)最佳實踐
在MySQL中可以使用單引號或雙引號來包裹字符串,下面這篇文章主要給大家介紹了關(guān)于Mysql插入帶有引號的字符串?dāng)?shù)據(jù)的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
解決MySQL Sending data導(dǎo)致查詢很慢問題的方法與思路
這篇文章主要介紹了解決MySQL Sending data導(dǎo)致查詢很慢問題的方法與思路,感興趣的小伙伴們可以參考一下2016-04-04
Mysql的Table doesn't exist問題及解決
這篇文章主要介紹了Mysql的Table doesn't exist問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12
mysql使用SQLyog導(dǎo)入csv數(shù)據(jù)不成功的解決方法
給mysql導(dǎo)入數(shù)據(jù),選中某個表選擇導(dǎo)入--導(dǎo)入使用本地csv數(shù)據(jù)即可,單有的時候不知道什么問題導(dǎo)入不成功2014-07-07
mysql數(shù)據(jù)庫limit的四種用法小結(jié)
mysql數(shù)據(jù)庫中l(wèi)imit子句可以被用于強(qiáng)制select語句返回指定的記錄數(shù),本文主要介紹了mysql數(shù)據(jù)庫limit的四種用法小結(jié),感興趣的可以了解一下2023-10-10

