mysql回表查詢

百萬級別的大表分頁查詢如何優化?

order by和group by這兩種情況要避免回表查詢。那麼先來了解下什麼是回表查詢。

 

 

以下文章來源於  https://www.cnblogs.com/yanggb/p/11252966.html   感謝作者

瞭解一下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, sex, flag),這裏的id是聚集索引,name則是普通索引。

表中有四條記錄:

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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章