覆盖索引与联合索引_浅析MySQL的索引覆盖和索引下推
寫在前面
在MySQL數(shù)據(jù)庫(kù)中,索引對(duì)查詢的速度有著至關(guān)重要的影響,理解索引也是進(jìn)行數(shù)據(jù)庫(kù)性能調(diào)優(yōu)的起點(diǎn),索引就是為了提高數(shù)據(jù)查詢的效率。今天我們來聊聊在MySQL索引優(yōu)化中兩種常見的方式,索引覆蓋和索引下推索引覆蓋
要了解索引覆蓋,需要先了解幾個(gè)索引的基礎(chǔ)知識(shí)
B+樹索引
B+樹索引是InnoDB中的一種很常見的索引類型。關(guān)于B+樹,這里不做深入的介紹,不太清楚的小胖友可以看單獨(dú)介紹B樹、B+樹的文章。簡(jiǎn)單來說,是因?yàn)?strong>使用B+樹存儲(chǔ)數(shù)據(jù)可以讓一個(gè)查詢盡量少的讀磁盤,從而減少查詢時(shí)磁盤I/O的時(shí)間。在 InnoDB 中,表都是根據(jù)主鍵順序以索引的形式存放的,這種存儲(chǔ)方式的表稱為索引組織表。InnoDB 使用了 B+ 樹索引模型,所以數(shù)據(jù)都是存儲(chǔ)在 B+ 樹中的。每一個(gè)索引在 InnoDB 里面對(duì)應(yīng)一棵 B+ 樹。舉例說明,假設(shè)我們有一張表,該表主鍵為id,且有用戶名(user_name)和用戶年齡(age)兩個(gè)字段,其中age字段上有索引,所以建表語(yǔ)句如下圖所示:表中有5條數(shù)據(jù)基于上面這種表設(shè)計(jì)和表中的數(shù)據(jù),在InnoDB中的索引結(jié)構(gòu)是下面這個(gè)樣子的根據(jù)葉子節(jié)點(diǎn)的內(nèi)容,索引的類型分為主鍵索引和非主鍵索引主鍵索引的葉子結(jié)點(diǎn)存的是整條記錄,如上圖紫色部分所示
非主鍵索引的葉子結(jié)點(diǎn)存的是主鍵的地址值,根據(jù)二級(jí)索引葉子結(jié)點(diǎn)中的地址可以找到主鍵索引中的這一條數(shù)據(jù)。所以非主鍵索引也被稱為二級(jí)索引,如上圖右半邊黃色部分所示
第一條語(yǔ)句使用主鍵作為檢索條件,即為主鍵查詢,根據(jù)上圖所示我們知道,如果是主鍵查詢,我們只需要搜索左邊這顆主鍵索引樹即可快速查詢到id=2的這條數(shù)據(jù)
第二條語(yǔ)句使用的是二級(jí)索引、即age作為檢索條件,這和主鍵查詢有什么區(qū)別呢?如果是二級(jí)索引查詢,則需要先搜索左側(cè)的age索引樹,得到id的值為2,再到右側(cè)的主鍵索引樹搜索一次。
像第二種查詢語(yǔ)句這樣,通過非主鍵索引查詢數(shù)據(jù)時(shí),我們先通過非主鍵索引樹查找到主鍵值,然后再在主鍵索引樹搜索一次(根據(jù)rowid再次到數(shù)據(jù)塊里取數(shù)據(jù)的操作),這個(gè)過程稱為回表,也就是說非主鍵索引查詢會(huì)比主鍵查詢多搜索一棵樹
索引覆蓋
結(jié)合上面的知識(shí)儲(chǔ)備,我們進(jìn)一步來優(yōu)化一下剛才的SQL
select *from lyb_test where age = 12當(dāng)這條語(yǔ)句執(zhí)行時(shí),我們知道會(huì)進(jìn)行兩次索引樹查詢,第一次在二級(jí)索引上查詢到主鍵索引的引用,然后到主鍵索引樹中查詢到所需要的數(shù)據(jù),這個(gè)過程我們稱之為回表。那為什么要有回表操作呢?由于查詢的結(jié)果是所有字段,所需要的數(shù)據(jù)只有主鍵上才有,所以不得不回表。我們?nèi)绻麑ql改造為下面這種方式:select id from lyb_test where age = 12由于查詢的值是ID,而id的值已經(jīng)在age索引樹上了,因此可以直接提供查詢結(jié)果,不需要回表。也就是說,當(dāng)SQL語(yǔ)句的所有查詢字段(select列)和查詢條件字段(where子句)全都包含在一個(gè)索引中,便可以直接使用索引查詢而不需要回表。即在這個(gè)查詢里,索引age已經(jīng)“覆蓋了”我們的查詢需求,故稱為索引覆蓋。
索引下推還是基于剛才的表結(jié)構(gòu)和數(shù)據(jù),我們現(xiàn)在針對(duì)user_name和age建立聯(lián)合索引,索引建立之后,查詢姓名以b開頭且年齡大于等于13的用戶信息,SQL語(yǔ)句如下:
select * from user_table where username like 'b%' and age >= 13語(yǔ)句的執(zhí)行過程有兩種可能性:根據(jù)(username,age)聯(lián)合索引查詢所有滿足名稱以"b"開頭的索引,然后回表查詢出相應(yīng)的全行數(shù)據(jù),再篩選出滿足年齡大于等于13的用戶數(shù)據(jù)。如果表中user_name以b開頭的數(shù)據(jù)有n條,則需要回表n次
根據(jù)(username,age)聯(lián)合索引查詢所有滿足名稱以"b"開頭的索引,然后直接再篩選出年齡大于等于13的索引,之后再回表查詢?nèi)袛?shù)據(jù)。經(jīng)過兩次篩選之后,回表次數(shù)一定小于上述第一種情況
索引下推一般可用于所求查詢字段(select列)不是/不全是聯(lián)合索引的字段,查詢條件為多條件查詢且查詢條件子句(where/order by)字段全是聯(lián)合索引。假設(shè)表t有聯(lián)合索引(a,b),下面語(yǔ)句可以使用索引下推提高效率
select?*?from?t?where?a?>?2?and?b?>?10上述就是索引覆蓋、回表、索引下推的相關(guān)概念和使用場(chǎng)景。當(dāng)然針對(duì)MySQL的索引優(yōu)化還有其他非常多的方式,我們可以在之后的文章中討論。本文到這里就結(jié)束啦,謝謝小伙伴們的閱讀~
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的覆盖索引与联合索引_浅析MySQL的索引覆盖和索引下推的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 史上最雷人的Cosplay图片集
- 下一篇: leetcode603. 连续空余座位(