mysql覆蓋索引與回表

2021-10-14 10:13:14 字數 1900 閱讀 4454

要說回表查詢,先要從innodb的索引實現說起。innodb有兩大類索引,一類是聚集索引(clustered index),一類是普通索引(secondary index)。

innodb的聚集索引

innodb聚集索引的葉子節點儲存行記錄,因此innodb必須要有且只有乙個聚集索引。

1.如果表定義了pk(primary key,主鍵),那麼pk就是聚集索引。

2.如果表沒有定義pk,則第乙個not null unique的列就是聚集索引。

3.否則innodb會另外建立乙個隱藏的rowid作為聚集索引。

這種機制使得基於pk的查詢速度非常快,因為直接定位的行記錄。

innodb的普通索引

innodb普通索引的葉子節點儲存主鍵值(myisam則是儲存的行記錄頭指標)。

什麼是回表查詢

假設有個t表(id pk, name key, ***, flag),這裡的id是聚集索引,name則是普通索引

idname***flag1sj

ma3zs

ma5ls

ma9ww

fb聚集索引的b+樹索引(id是pk,葉子節點儲存行記錄):

普通索引的b+樹索引(name是key,葉子節點儲存pk值,即id):

普通索引因為無法直接定位行記錄,其查詢過程在通常情況下是需要掃瞄兩遍索引樹的。

select * from t where name = 'lisi';
這裡的執行過程是這樣的:

粉紅色的路徑需要掃瞄兩遍索引樹,第一遍先通過普通索引定位到主鍵值id=5,然後第二遍再通過聚集索引定位到具體行記錄。這就是所謂的回表查詢,即先定位主鍵值,再根據主鍵值定位行記錄,效能相對於只掃瞄一遍聚集索引樹的效能要低一些。

索引覆蓋是一種避免回表查詢的優化策略。具體的做法就是將要查詢的資料作為索引列建立普通索引(可以是單列索引,也可以乙個索引語句定義所有要查詢的列,即聯合索引),這樣的話就可以直接返回索引中的的資料,不需要再通過聚集索引去定位行記錄,避免了回表的情況發生。

覆蓋索引的定義與注意事項

如果乙個索引覆蓋(包含)了所有需要查詢的字段的值,這個索引就是覆蓋索引。因為索引中已經包含了要查詢的字段的值,因此查詢的時候直接返回索引中的字段值就可以了,不需要再到表中查詢,避免了對主鍵索引的二次查詢,也就提高了查詢的效率。

要注意的是,不是所有型別的索引都可以成為覆蓋索引的。因為覆蓋索引必須要儲存索引的列值,而雜湊索引、空間索引和全文索引等都不儲存索引列值,索引mysql只能使用b-tree索引做覆蓋索引。

另外,當發起乙個被索引覆蓋的查詢(索引覆蓋查詢)時,在explain(執行計畫)的extra列可以看到【using index】的資訊。

1.索引條目通常遠小於資料行的大小,因為覆蓋索引只需要讀取索引,極大地減少了資料的訪問量。

2.索引是按照列值順序儲存的,對於io密集的範圍查詢會比隨機從磁碟讀取每一行資料的io小很多。

3.一些儲存引擎比如myisam在記憶體中只快取索引,資料則依賴作業系統來快取,因此要訪問資料的話需要一次系統呼叫,使用覆蓋索引則避免了這一點。

4.由於innodb的聚簇索引,覆蓋索引對innodb引擎下的資料庫表特別有用。因為innodb的二級索引在葉子節點中儲存了行的主鍵值,如果二級索引能夠覆蓋查詢,就避免了對主鍵索引的二次查詢。

Mysql索引 回表 索引覆蓋

1.先說什麼是索引?索引是一種資料結構 不同引擎對索引的實現方式不同,innodb採用b 樹作為索引結構。2.聚簇索引 非聚簇索引索引可分為聚簇索引和非聚簇索引兩種。聚簇索引 clustered index 聚簇索引的資料的物理存放順序與索引順序是一致的。非聚簇索引 二級索引 secondary i...

MySQL索引,回表,索引覆蓋

多讀多寫多記錄,多學多練多思考。banana.banuit gang 香柚幫 mysql innodb的主鍵索引是簇集索引,也就是索引的葉子節點存的是整個單條記錄的所有字段值,不是主鍵索引的就是非簇集索引,非簇集索引的葉子節點存的是主鍵欄位的值。回表是什麼意思?就是你執行一條sql語句,需要從兩個b...

MySQL 的覆蓋索引與回表

如果表設定了主鍵,則主鍵就是聚簇索引 如果表沒有主鍵,則會預設第乙個not null,且唯一 unique 的列作為聚簇索引 以上都沒有,則會預設建立乙個隱藏的row id作為聚簇索引 innodb的聚簇索引的葉子節點儲存的是行記錄 其實是頁結構,乙個頁包含多行資料 innodb必須要有至少乙個聚簇...