mysql中的回表查詢與索引覆蓋

2021-10-07 02:50:50 字數 2231 閱讀 3237

了解一下mysql中的回表查詢與索引覆蓋。

回表查詢

要說回表查詢,先要從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則是普通索引。

表中有四條記錄:

id name *** flag

1 sj m a

3 zs m a

5 ls m a

9 ww f b

聚集索引的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的二級索引在葉子節點中儲存了行的主鍵值,如果二級索引能夠覆蓋查詢,就避免了對主鍵索引的二次查詢。

什麼是二級索引(secondary indexes)

對於innodb表,在非主鍵列的其他列上建的索引就是二級索引(因為聚集索引只有乙個)。二級索引可以有0個,1個或者多個。二級索引和聚集索引的區別是什麼呢?二級索引的節點頁和聚集索引一樣,只存被索引列的值,而二級索引的葉子頁除了索引列值,還存這一列對應的主鍵值。

參考文件:

MySQL 聚簇索引,輔助索引,回表查詢,索引覆蓋

索引覆蓋 也叫聚簇索引,是一種資料儲存方式 將索引和資料儲存在一起 是按照每張表的主鍵構造一顆b 樹,同時葉子節點中存放的就是整張表的行記錄資料,也將聚集索引的葉子節點稱為資料頁。這個特性決定了索引組織表中資料也是索引的一部分,每張表只能擁有乙個聚簇索引。b 樹將資料儲存與索引放到了一塊,找到索引也...

MySQL的回表查詢與索引覆蓋查詢

上篇講到,mysql中分為聚集索引和非聚集索引。非聚集索引的btree葉子節點中儲存的是當行資料的pk。所以為了取到具體資料,則需要通過pk回到聚集索引裡去查詢資料。著就叫回表查詢。掃瞄了2次索引樹。所以效率相對較低。假設有個t表,如下圖所示。id是聚集索引,name則是普通索引。idname 1小...

mysql覆蓋索引與回表

要說回表查詢,先要從innodb的索引實現說起。innodb有兩大類索引,一類是聚集索引 clustered index 一類是普通索引 secondary index innodb的聚集索引 innodb聚集索引的葉子節點儲存行記錄,因此innodb必須要有且只有乙個聚集索引。1.如果表定義了pk...