mysql覆蓋索引詳解

覆蓋索引的定義:mysql

若是一個索引包含(或覆蓋)全部須要查詢的字段的值,稱爲‘覆蓋索引’。即只需掃描索引而無須回表。sql


只掃描索引而無需回表的優勢:
    1.索引條目一般遠小於數據行大小,只須要讀取索引,則mysql會極大地減小數據訪問量。
    2.由於索引是按照列值順序存儲的,因此對於IO密集的範圍查找會比隨機從磁盤讀取每一行數據的IO少不少。
    3.一些存儲引擎如myisam在內存中只緩存索引,數據則依賴於操做系統來緩存,所以要訪問數據須要一次系統調用
    4.innodb的聚簇索引,覆蓋索引對innodb表特別有用。(innodb的二級索引在葉子節點中保存了行的主鍵值,因此若是二級主鍵可以覆蓋查詢,則能夠避免對主鍵索引的二次查詢)
緩存

覆蓋索引必需要存儲索引列的值,而哈希索引、空間索引和全文索引不存儲索引列的值,因此mysql只能用B-tree索引作覆蓋索引。
服務器

當發起一個索引覆蓋查詢時,在explain的extra列能夠看到using index的信息
優化

覆蓋索引的坑:mysql查詢優化器會在執行查詢前判斷是否有一個索引能進行覆蓋,假設索引覆蓋了where條件中的字段,但不是整個查詢涉及的字段,mysql5.5和以前的版本也會回表獲取數據行,儘管並不須要這一行且最終會被過濾掉。
spa

如上圖則沒法使用覆蓋查詢,緣由:
    1.沒有任何索引可以覆蓋這個索引。由於查詢從表中選擇了全部的列,而沒有任何索引覆蓋了全部的列。
操作系統

    2.mysql不能在索引中執行LIke操做。mysql能在索引中作最左前綴匹配的like比較,可是若是是通配符開頭的like查詢,存儲引擎就沒法作比較匹配。這種狀況下mysql只能提取數據行的值而不是索引值來作比較設計

優化後SQL:添加索引(artist,title,prod_id),使用了延遲關聯(延遲了對列的訪問)

說明:在查詢的第一階段可使用覆蓋索引,在from子句中的子查詢找到匹配的prod_id,而後根據prod_id值在外層查詢匹配獲取須要的全部值。3d

5.5時API設計不容許mysql將過濾條件傳到存儲引擎層(是把數據從存儲引擎拉到服務器層,在根據條件過濾),5.6以後因爲ICP這個特性改善了查詢執行方式blog

相關文章
相關標籤/搜索