覆蓋索引


前提

為了通用,更為了避免造數據的痛苦,文中所涉及表、數據,均來自於MySQL官網提供的示例庫employees,可通過 https://launchpad.net/test-db/employees-db-1/1.0.6 自行下載。

什么是覆蓋索引

如果一個索引包含(或者說覆蓋)所有需要查詢的字段的值,我們就稱之為“覆蓋索引”。

不是所有的類型的索引都可以成為覆蓋索引,覆蓋索引必須要存儲索引列的值,而哈希索引,空間索引和全文索引等都不存儲引列的值,所以MySQL只能使用B-Tree索引做覆蓋索引。另外不同的存儲引擎實現覆蓋索引的方式也不同,而且不是所有的覆蓋索引都支持覆蓋索引。

當發起一個被索引覆蓋的查詢(也叫索引覆蓋查詢)時,在EXPLAIN的Extra列可以看到“Using index”的信息。

覆蓋索引是非常有用的工具,能夠極大的提高性能。考慮一下如果查詢只需要索引而無需返回表,會帶來多大好處:

  索引條目通常遠小於數據行大小,所以只需要讀取索引,那么MySQL就會極大的減少數據訪問量。這對緩存的負載非常重要,因為這種情況下相應時間大部分花費在數據拷貝上。覆蓋索引對於I/O密集型的應用也有幫助,以為索引比數據更小,更容易全部放入內存中(這對於MyIsam 尤其正確,因為myisam 能壓縮索引以變得更小)。

  因為索引是按照列值順序存儲的(至少在單個頁內是如此),所以對於IO密集型的范圍查詢會比隨機從磁盤讀取沒以后數據的io要小的多。對於某些存儲引擎,例如MyISAM,甚至可以通過OPTIMIZE命令使得索引完全順序排列,這讓簡單的范圍查詢能使用完全順序的索引訪問。

  一些存儲引擎如MyISAM,在內存中只緩存索引,數據則依賴操作系統來緩存,因此要訪問數據需要一次系統調用。這可能會導致嚴重的性能問題,尤其是那些系統調用占了數據訪問中的最大開銷的場景。

  由於InnoDB的聚簇索引,覆蓋索引對InnoDB表特別有用。InnoDB的二級索引在葉子節點中保存了行的主鍵值,所以如果二級主鍵能夠覆蓋查詢,則可以避免對主鍵索引的二次查詢。在所有這些場景中,索引中滿足查詢的成本一般比查詢要小的多。

 

在employees表上創建索引  alter table employees add index `idx_first_last_birth`(first_name,last_name,birth_date);

創建索引后執行查詢

 

 

 對於以上SQL對索引的使用情況:
1:所有信息都可以從idx_first_last_birth索引中獲取(即索引已覆蓋SQL所需所有信息)
2:所有信息都可以從idx_first_last_birth索引中獲取
3:所有信息都可以從idx_first_last_birth索引中獲取,並且也能通過索引直接獲取排序
4:所有信息都可以從idx_first_last_birth索引中獲取,但無法通過索引直接獲取排序,需有額外的排序過程,但索引中依然包含排序字段。
5:where條件能通過idx_first_last_birth索引過濾出結果集(此時仍需回表查出select部分所需字段返回給用戶)
6:先通過first_name字段所在idx_first_last_birth索引快速過濾出結果集1,在回表獲取表中其它字段信息,並通過hire_date字段過濾出結果集1中的符合條件的數據,最終反饋給用戶。

explain 相關列解讀請參考 http://www.cnblogs.com/ggjucheng/archive/2012/11/11/2765237.html 

 

警告

        創建這些索引只是用來描述確認覆蓋索引的過程,但在生產環境中它們可能並不是理想的索引。由於數據集大小有限,我們在這些例子中使用了一個長字符列。隨着數據容量的增加,尤其是超過內存和磁盤最大容量的時候,為一個大型列創建索引可能會對系統整體性能有影響。覆蓋索引對於那些使用了很多較小長度的主碼和外鍵約束的大型規范化模式來說是理想的優化方式。

參考文獻

[1] Baron Scbwartz等 著, 寧海元等 譯;高性能MySQL(第三版)(High Performance MySQL);電子工業出版社,2010


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM