InnoDB主鍵索引樹和二級(jí)索引樹的場(chǎng)景分析
我們這里討論InnoDB存儲(chǔ)引擎,數(shù)據(jù)和索引存儲(chǔ)在同一個(gè)文件student.ibd
場(chǎng)景1:主鍵索引樹
uid是主鍵,其他字段沒有添加任何索引
select * from student;
如果是這樣查詢,這表示整表搜索,從左到右遍歷葉子節(jié)點(diǎn)鏈表,從小到大訪問
select * from student where uid<5;
如果是這樣查詢,這表示范圍查詢,就直接在有序鏈表中遍歷搜索就可以了,直到遍歷到第一個(gè)不小于5的key結(jié)束遍歷
select * from student where uid=5;
如果是這樣查詢,這表示等值查詢,在索引樹上進(jìn)行二分查找即可
由于name沒有索引,于是做整表搜索
select * from student where name='linfeng';
場(chǎng)景2:二級(jí)索引樹
uid是主鍵,以name創(chuàng)建了普通索引(二級(jí)索引)
以name為索引構(gòu)建的索引樹,稱為輔助索引樹,也叫做二級(jí)索引樹。key是輔助索引字段name的值,然后還有外加uid主鍵的值
在輔助索引樹上,key是輔助索引的值,也就是name;data數(shù)據(jù)值是所在記錄行的主鍵值(PRIMARY KEY),也就是uid(并不是表的一行數(shù)據(jù))
分析語句1:
select name from student where name='linfeng';
因?yàn)檫^濾字段是name且 只select了name一個(gè)字段,name有索引,索引樹上直接就有,所以從name的二級(jí)索引樹上去等值匹配linfeng
分析語句2:
select uid,name from student where name='linfeng';
這種情況select的是name和uid,而這些在二級(jí)索引樹上也是直接就有,所以搜索二級(jí)索引樹就完事了。
分析語句3:
select * from student where name='linfeng';
這種情況下就涉及到回表了,這是一個(gè)很重要的概念。由于name字段有索引,所以我們會(huì)到name字段構(gòu)建的二級(jí)索引樹上去查找。但二級(jí)索引樹沒有linfeng這個(gè)人所有的信息,所以完整的查詢過程應(yīng)該是這樣的:
- 用linfeng到二級(jí)索引樹上進(jìn)行匹配,拿到二級(jí)索引樹上存儲(chǔ)的uid
- 然后拿著這個(gè)uid去主索引樹上去匹配,最后拿到linfeng的所有信息(回表)
而這個(gè)回表意味著更多的磁盤I/O,會(huì)影響效率,如果業(yè)務(wù)只需要uid、name,就別寫select *了,這樣可以避免回表
分析語句4:
我們刪除name的索引后執(zhí)行以下語句
select * from student where age=20 order by name;
沒有用到索引,還使用外部排序了。此外我們還看到using filesort,這時(shí)需要優(yōu)化了。
我們的過濾條件是age,先給age添加索引,看看行不行
可以看到,age命中索引了,查詢age所在的索引樹。由于我們寫的是select *
,依然存在回表。還有using filesort,因?yàn)槭褂胊ge=20查詢到的結(jié)果是多個(gè),然而name此時(shí)是沒有順序的,所以還需要再進(jìn)行外部排序。
那能不能通過給name加載索引來解決問題呢?
不能,因?yàn)橐淮蜸QL執(zhí)行只能用到1個(gè)索引,搜索了這個(gè)字段的索引樹就不會(huì)再去搜索另一個(gè)字段的索引樹了,因?yàn)榧虞d索引是要耗費(fèi)磁盤I/O的,查找多個(gè)索引樹就太慢了!
分析:既然索引樹上只能存自己建立的索引字段以及主鍵,那我們把需要查詢的字段都設(shè)置成索引不就好了?
解決方法:我們可以在二級(jí)索引樹上的key:age+name,形成聯(lián)合索引,先按age排序,age相同了,再按name排序
再次select *
這時(shí)候就使用到聯(lián)合索引了,而且沒有using filesort,這次是這樣查詢的:
先用age=20在輔助索引樹上查找,如果數(shù)據(jù)足夠會(huì)找到多個(gè)結(jié)果,這個(gè)結(jié)果就是已經(jīng)排好序的,不需要再using filesort
我們現(xiàn)在直接用第二個(gè)字段name作為過濾條件
我們看到這里沒有用到索引,因?yàn)槲覀冇?age,name)創(chuàng)建索引,是先按age排序,再按name排序。如果我們只用name作為過濾條件,這就沒有辦法使用索引匹配了,因?yàn)槭莾?yōu)先用age排序。
所以我們經(jīng)常說,多列索引一定要使用到第1個(gè)字段,這樣才能用到索引!
在建立(age,name)聯(lián)合索引的情況下,以下操作不回表(到二級(jí)索引樹上搜索,再去主索引樹上搜索):
- select age
- select age, name
- select uid,age,name
以下操作要回表
- select *
- select age,name,sex
到此這篇關(guān)于InnoDB主鍵索引樹和二級(jí)索引樹的文章就介紹到這了,更多相關(guān)InnoDB索引樹內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何使用navicat遠(yuǎn)程連接openGauss
公司要在openEuler系統(tǒng)中安裝openGauss數(shù)據(jù)庫,經(jīng)過幾天的查資料,終于是安裝成功了,并且能在navicat中遠(yuǎn)程連接使用,本文給大家介紹如何使用navicat遠(yuǎn)程連接openGauss,感興趣的朋友跟隨小編一起看看吧2023-10-10時(shí)序數(shù)據(jù)庫TDengine寫入查詢的問題分析
最近TDengine很火,本人也一直很早就有關(guān)注,其官方給出的測(cè)試性能結(jié)果很喜人,所以一開源,本人就進(jìn)行了相關(guān)調(diào)研,最終發(fā)現(xiàn)還是存在著一定的問題,期待后續(xù)的完善吧2022-03-03Django項(xiàng)目?jī)?yōu)化數(shù)據(jù)庫操作總結(jié)
這篇文章主要介紹了Django項(xiàng)目中優(yōu)化數(shù)據(jù)庫操作總結(jié),有需要的朋友可以借鑒參考下,希望可以有所幫助,祝大家共進(jìn)步,早日升職加薪2021-09-09一篇文章帶你了解數(shù)據(jù)庫中g(shù)roup by的用法
這篇文章主要給大家介紹了關(guān)于數(shù)據(jù)庫中g(shù)roup by的法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用數(shù)據(jù)庫具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Navicat11全系列激活教程圖文詳解(Navicat注冊(cè)機(jī))
這篇文章主要介紹了Navicat11全系列激活教程圖文詳解(注冊(cè)機(jī)),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11