1. 程式人生 > 資料庫 >Mysql覆蓋索引詳解

Mysql覆蓋索引詳解

概念

如果索引包含所有滿足查詢需要的資料的索引成為覆蓋索引(Covering Index),也就是平時所說的不需要回表操作

判斷標準

使用explain,可以通過輸出的extra列來判斷,對於一個索引覆蓋查詢,顯示為using index,MySQL查詢優化器在執行查詢前會決定是否有索引覆蓋查詢

注意

1、覆蓋索引也並不適用於任意的索引型別,索引必須儲存列的值

2、Hash 和full-text索引不儲存值,因此MySQL只能使用B-TREE

3、並且不同的儲存引擎實現覆蓋索引都是不同的

4、並不是所有的儲存引擎都支援它們

5、如果要使用覆蓋索引,一定要注意SELECT 列表值取出需要的列,不可以是SELECT *,因為如果將所有欄位一起做索引會導致索引檔案過大,查詢效能下降,不能為了利用覆蓋索引而這麼做

如果一個索引包含(或覆蓋)所有需要查詢的欄位的值,稱為‘覆蓋索引'。即只需掃描索引而無須回表。

只掃描索引而無需回表的優點:

1.索引條目通常遠小於資料行大小,只需要讀取索引,則mysql會極大地減少資料訪問量。

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

3.一些儲存引擎如myisam在記憶體中只快取索引,資料則依賴於作業系統來快取,因此要訪問資料需要一次系統呼叫

4.innodb的聚簇索引,覆蓋索引對innodb表特別有用。(innodb的二級索引在葉子節點中儲存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢)

覆蓋索引必須要儲存索引列的值,而雜湊索引、空間索引和全文索引不儲存索引列的值,所以mysql只能用B-tree索引做覆蓋索引。

當發起一個索引覆蓋查詢時,在explain的extra列可以看到using index的資訊

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

如上圖則無法使用覆蓋查詢,原因:

1.沒有任何索引能夠覆蓋這個索引。因為查詢從表中選擇了所有的列,而沒有任何索引覆蓋了所有的列。

2.mysql不能在索引中執行LIke操作。mysql能在索引中做最左字首匹配的like比較,但是如果是萬用字元開頭的like查詢,儲存引擎就無法做比較匹配。這種情況下mysql只能提取資料行的值而不是索引值來做比較

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

說明:在查詢的第一階段可以使用覆蓋索引,在from子句中的子查詢找到匹配的prod_id,然後根據prod_id值在外層查詢匹配獲取需要的所有值。

5.5時API設計不允許mysql將過濾條件傳到儲存引擎層(是把資料從儲存引擎拉到伺服器層,在根據條件過濾),5.6之後由於ICP這個特性改善了查詢執行方式

當MySQL不能使用索引進行排序時,就會利用自己的排序演算法(快速排序演算法)在記憶體(sort buffer)中對資料進行排序,如果記憶體裝載不下,它會將磁碟上的資料進行分塊,再對各個資料塊進行排序,然後將各個塊合併成有序的結果集(實際上就是外排序)

對於filesort,MySQL有兩種排序演算法

1、兩遍掃描演算法(Two passes)

實現方式是先將須要排序的欄位和可以直接定位到相關行資料的指標資訊取出,然後在設定的記憶體(通過引數sort_buffer_size設定)中進行排序,完成排序之後再次通過行指標資訊取出所需的Columns

注:該演算法是4.1之前採用的演算法,它需要兩次訪問資料,尤其是第二次讀取操作會導致大量的隨機I/O操作。另一方面,記憶體開銷較小

2、 一次掃描演算法(single pass)

該演算法一次性將所需的Columns全部取出,在記憶體中排序後直接將結果輸出
注: 從 MySQL 4.1 版本開始使用該演算法。它減少了I/O的次數,效率較高,但是記憶體開銷也較大。如果我們將並不需要的Columns也取出來,就會極大地浪費排序過程所需要 的記憶體。在 MySQL 4.1 之後的版本中,可以通過設定 max_length_for_sort_data 引數來控制 MySQL 選擇第一種排序演算法還是第二種。當取出的所有大欄位總大小大於 max_length_for_sort_data 的設定時,MySQL 就會選擇使用第一種排序演算法,反之,則會選擇第二種。為了儘可能地提高排序效能,我們自然更希望使用第二種排序演算法,所以在 Query 中僅僅取出需要的 Columns 是非常有必要的。

當對連線操作進行排序時,如果ORDER BY僅僅引用第一個表的列,MySQL對該表進行filesort操作,然後進行連線處理,此時,EXPLAIN輸出“Using filesort”;否則,MySQL必須將查詢的結果集生成一個臨時表,在連線完成之後進行filesort操作,此時,EXPLAIN輸出 “Using temporary;Using filesort”

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對我們的支援。如果你想了解更多相關內容請檢視下面相關連結