MySQLl優(yōu)化:為什么要用覆蓋索引?
引言:
覆蓋索引是一種利用二級索引的葉子節(jié)點(diǎn)包含了所有需要查詢的列數(shù)據(jù),從而避免回表操作的查詢方式?;乇聿僮魇侵竿ㄟ^二級索引找到主鍵值,再根據(jù)主鍵值在聚簇索引中查找完整的記錄?;乇聿僮鲿黾哟疟P的隨機(jī)IO,降低查詢效率。使用覆蓋索引可以減少樹的搜索次數(shù),提升查詢性能。
先了解三個概念:
InnoDB索引模型:
在InnoDB中,表都是根據(jù)主鍵順序以索引的形式存放的,這種存儲方式的表稱為索引組織表。InnoDB使用了B+樹索引模型,所以數(shù)據(jù)都是存儲在B+樹中的。
主鍵索引和非主鍵索引的區(qū)別
主鍵索引又叫聚簇索引,非主鍵索引又叫普通索引,那么這兩種索引有什么區(qū)別呢?
主鍵索引的葉子節(jié)點(diǎn)存放的是整行數(shù)據(jù),非主鍵索引的葉子節(jié)點(diǎn)存放的是主鍵的值。
假設(shè)有一張User表(id,age,name,address),其中有id和age兩個字段,其中id是主鍵,age是普通索引,有幾行數(shù)據(jù)u1-u5的(id,age)的值是(100,1)、(200,2)、(300,3)、(500,5)和(600,6) ,此時(shí)的兩棵樹的示例如下:
從上圖可以看出來,基于主鍵索引的樹的葉子節(jié)點(diǎn)存放的是整行User數(shù)據(jù),基于普通索引age的葉子節(jié)點(diǎn)存放的是id(主鍵)的值。
總結(jié)區(qū)別:
- 聚簇索引是指按照數(shù)據(jù)的物理順序存儲的索引,通常是主鍵索引。聚簇索引的葉子節(jié)點(diǎn)直接存儲了數(shù)據(jù)行,因此通過聚簇索引可以快速找到數(shù)據(jù)。一個表只能有一個聚簇索引。
- 非聚簇索引是指按照數(shù)據(jù)的邏輯順序存儲的索引,通常是普通索引或唯一索引。非聚簇索引的葉子節(jié)點(diǎn)存儲了主鍵值或者指針,因此通過非聚簇索引需要再次回表查詢數(shù)據(jù)。一個表可以有多個非聚簇索引。
- 聚簇索引和非聚簇索引的性能優(yōu)劣取決于查詢語句和數(shù)據(jù)量。一般來說,聚簇索引對于范圍查詢和全表掃描更有優(yōu)勢,而非聚簇索引對于單點(diǎn)查詢和覆蓋查詢更有優(yōu)勢。
什么是回表?
假設(shè)有一條查詢語句如下:
select * from user where age=3;
上面這條sql語句執(zhí)行的過程如下:
- 根據(jù)age這個普通索引在age索引樹上搜索,得到主鍵id的值為300。
- 因?yàn)閍ge索引樹并沒有存儲User的全部數(shù)據(jù),因此需要根據(jù)在age索引樹上查詢到的主鍵id的值300再到id索引樹搜索一次,查詢到了u3。
- 返回結(jié)果。
上述執(zhí)行的過程中,從age索引樹再到id索引樹的查詢的過程叫做回表(回到主鍵索引樹搜索的過程)。
也就是說通過非主鍵索引的查詢需要多掃描一棵索引樹,因此需要盡量使用主鍵索引查詢。
為什么使用覆蓋索引?
有了上述提及到的幾個概念,便能很清楚的理解為什么覆蓋索引能夠提升查詢效率了,因?yàn)樯倭艘淮位乇淼倪^程。
假設(shè)我們使用覆蓋索引查詢,語句如下:
select id from user where age=3;
這條語句執(zhí)行過程很簡單,直接在age索引樹中二級索引葉子節(jié)點(diǎn)就能查詢到id的值,不用再去id索引樹中查找其他的數(shù)據(jù),避免了回表。
總結(jié):
覆蓋索引的使用能夠減少樹的搜索次數(shù),避免了回表,顯著提升了查詢性能,因此覆蓋索引是一個常用的性能優(yōu)化手段。