圖文詳解Mysql索引的最左前綴原則
前言
之所以有這個(gè)最左前綴索引
歸根結(jié)底是mysql的數(shù)據(jù)庫結(jié)構(gòu) B+樹
在實(shí)際問題中 比如
索引index (a,b,c)有三個(gè)字段,
使用查詢語句select * from table where c = '1' ,sql語句不會(huì)走index索引的
select * from table where b =‘1’ and c ='2' 這個(gè)語句也不會(huì)走index索引
1. 定義
最左前綴匹配原則:在MySQL建立聯(lián)合索引時(shí)會(huì)遵守最左前綴匹配原則,即最左優(yōu)先,在檢索數(shù)據(jù)時(shí)從聯(lián)合索引的最左邊開始匹配
為了更好辨別這種情況,通過建立表格以及索引的情況進(jìn)行分析
2. 全索引順序
建立一張表,建立一個(gè)聯(lián)合索引,如果順序顛倒,其實(shí)還是可以識(shí)別的,但是一定要有它的全部部分
建立表
CREATE TABLE staffs(
id INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(24) NOT NULL DEFAULT'' COMMENT'姓名',
`age` INT NOT NULL DEFAULT 0 COMMENT'年齡',
`pos` VARCHAR(20) NOT NULL DEFAULT'' COMMENT'職位',
`add_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'入職時(shí)間'
)CHARSET utf8 COMMENT'員工記錄表';
INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('z3',22,'manager',NOW());
INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('July',23,'dev',NOW());
INSERT INTO staffs(`name`,`age`,`pos`,`add_time`) VALUES('2000',23,'dev',NOW());
建立索引ALTER TABLE staffs ADD INDEX index_staffs_nameAgePos(name,age,pos);
索引的順序位name-age-pos
顯示其索引有沒有show index from staffs;

通過顛倒其左右順序,其執(zhí)行都是一樣的
主要的語句是這三句
explain select *from staffs where name='z3'and age=22 and pos='manager';explain select *from staffs where pos='manager' and name='z3'and age=22;explain select *from staffs where age=22 and pos='manager' and name='z3';

以上三者的順序顛倒,都使用到了聯(lián)合索引
最主要是因?yàn)镸ySQL中有查詢優(yōu)化器explain,所以sql語句中字段的順序不需要和聯(lián)合索引定義的字段順序相同,查詢優(yōu)化器會(huì)判斷糾正這條SQL語句以什么樣的順序執(zhí)行效率高,最后才能生成真正的執(zhí)行計(jì)劃
不論以何種順序都可使用到聯(lián)合索引
3. 部分索引順序
3.1 正序
如果是按照順序(缺胳膊斷腿的),都是一樣的
explain select *from staffs where name=‘z3’;explain select *from staffs where name='z3’and age=22;explain select *from staffs where name='z3’and age=22;

其type都是ref類型,但是其字段長度會(huì)有微小變化,也就是它定義的字長長度變化而已
3.2 亂序
如果部分索引的順序打亂
- 只查第一個(gè)索引
explain select *from staffs where name='z3'; - 跳過中間的索引
explain select *from staffs where name='z3' and pos='manager'; - 只查最后的索引
explain select *from staffs where pos='manager';

可以發(fā)現(xiàn)正序的時(shí)候
如果缺胳膊少腿,也是按照正常的索引
即使跳過了中間的索引,也是可以使用到索引去查詢
但是如果只查最后的索引
type就是all類型,直接整個(gè)表的查詢了(這是因?yàn)闆]有從name一開始匹配,直接匹配pos的話,會(huì)顯示無序,)
有些時(shí)候type就是index類型,這是因?yàn)檫€是可以通過索引進(jìn)行查詢
index是對(duì)所有索引樹進(jìn)行掃描,而all是對(duì)整個(gè)磁盤的數(shù)據(jù)進(jìn)行全表掃描
4. 模糊索引
類似模糊索引就會(huì)使用到like的語句
所以下面的三條語句
如果復(fù)合最左前綴的話,會(huì)使用到range或者是index的類型進(jìn)行索引
explain select *from staffs where name like '3%';最左前綴索引,類型為index或者rangeexplain select *from staffs where name like '%3%';類型為all,全表查詢explain select *from staffs where name like '%3%';,類型為all,全表查詢

5. 范圍索引
如果查詢多個(gè)字段的時(shí)候,出現(xiàn)了中間是范圍的話,建議刪除該索引,剔除中間索引即可
具體思路如下
建立一張單表
CREATE TABLE IF NOT EXISTS article( id INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, author_id INT(10) UNSIGNED NOT NULL, category_id INT(10) UNSIGNED NOT NULL, views INT(10) UNSIGNED NOT NULL, comments INT(10) UNSIGNED NOT NULL, title VARCHAR(255) NOT NULL, content TEXT NOT NULL ); INSERT INTO article(author_id,category_id,views,comments,title,content) VALUES (1,1,1,1,'1','1'), (2,2,2,2,'2','2'), (1,1,3,3,'3','3');
經(jīng)過如下查詢:
explain SELECT id, author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1;

發(fā)現(xiàn)其上面的單表查詢,不是索引的話,他是進(jìn)行了全表查詢,而且在extra還出現(xiàn)了Using filesort等問題
所以思路可以有建立其復(fù)合索引
具體建立復(fù)合索引有兩種方式:
create index idx_article_ccv on article(category_id,comments,views);ALTER TABLE 'article' ADD INDEX idx_article_ccv ( 'category_id , 'comments', 'views' );

但這只是去除了它的范圍,如果要去除Using filesort問題的話,還要將其中間的條件范圍改為等于號(hào)才可滿足
發(fā)現(xiàn)其思路不行,所以刪除其索引 DROP INDEX idx_article_ccv ON article;

主要的原因是:
這是因?yàn)榘凑誃Tree索引的工作原理,先排序category_id,如果遇到相同的category_id則再排序comments,如果遇到相同的comments 則再排序views。
當(dāng)comments字段在聯(lián)合索引里處于中間位置時(shí),因comments > 1條件是一個(gè)范圍值(所謂range),MySQL無法利用索引再對(duì)后面的views部分進(jìn)行檢索,即range類型查詢字段后面的索引無效。
所以建立復(fù)合索引是對(duì)的
但是其思路要避開中間那個(gè)范圍的索引進(jìn)去
只加入另外兩個(gè)索引即可create index idx_article_cv on article(category_id, views);

總結(jié)
到此這篇關(guān)于通過Mysql索引的最左前綴原則的文章就介紹到這了,更多相關(guān)Mysql索引最左前綴原則內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
全面分析MySQL?ERROR?1045出現(xiàn)的原因及解決
這篇文章主要介紹了全面分析MySQL?ERROR?1045出現(xiàn)的原因及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
一次非法關(guān)機(jī)導(dǎo)致mysql數(shù)據(jù)表損壞的實(shí)例解決
本文介紹由于非法硬件關(guān)機(jī),造成了mysql的數(shù)據(jù)表損壞,數(shù)據(jù)庫不能正常運(yùn)行的一個(gè)實(shí)例,接下來是作者排查錯(cuò)誤的過程,希望對(duì)大家能有所幫助2013-01-01
mysql使用mysqld_multi部署單機(jī)多實(shí)例的方法教程
這篇文章主要給大家介紹了關(guān)于mysql使用mysqld_multi部署單機(jī)多實(shí)例的相關(guān)資料,文中通過示例代碼將實(shí)現(xiàn)的步驟一步步介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03
DQL命令查詢數(shù)據(jù)實(shí)現(xiàn)方法詳解
DQL(Data?Query?Language,數(shù)據(jù)查詢語言),查詢數(shù)據(jù)庫數(shù)據(jù),如SELECT語句,簡單的單表查詢或多表的復(fù)雜查詢和嵌套查詢,數(shù)據(jù)庫語言中最核心、最重要的語句,使用頻率最高的語句2022-09-09
MySQL按時(shí)間統(tǒng)計(jì)數(shù)據(jù)的方法總結(jié)
在本篇MYSQL的內(nèi)容里,我們給大家整理了關(guān)于按時(shí)間統(tǒng)計(jì)數(shù)據(jù)的方法內(nèi)容,有需要的朋友們學(xué)習(xí)下。2019-02-02
Django連接本地mysql數(shù)據(jù)庫(pycharm)的步驟
這篇文章主要介紹了Django連接本地mysql數(shù)據(jù)庫(pycharm)的步驟,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
MySQL函數(shù)date_format()日期格式轉(zhuǎn)換的實(shí)現(xiàn)
本文主要介紹了MySQL函數(shù)date_format()日期格式轉(zhuǎn)換的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08

