瞭解一下MySQL中的回表查詢與索引覆蓋。數據庫
回表查詢緩存
要說回表查詢,先要從InnoDB的索引實現提及。InnoDB有兩大類索引,一類是彙集索引(Clustered Index),一類是普通索引(Secondary Index)。性能
InnoDB的彙集索引優化
InnoDB彙集索引的葉子節點存儲行記錄,所以InnoDB必需要有且只有一個彙集索引。spa
1.若是表定義了PK(Primary Key,主鍵),那麼PK就是彙集索引。操作系統
2.若是表沒有定義PK,則第一個NOT NULL UNIQUE的列就是彙集索引。指針
3.不然InnoDB會另外建立一個隱藏的ROWID做爲彙集索引。code
這種機制使得基於PK的查詢速度很是快,由於直接定位的行記錄。blog
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的二級索引在葉子節點中保存了行的主鍵值,若是二級索引可以覆蓋查詢,就避免了對主鍵索引的二次查詢。
"時刻保持謙虛,高情商是軟實力。"