覆蓋索引有何用?


覆蓋索引有何用?

通常開發人員會根據查詢的where條件來創建合適的索引,但是優秀的索引設計應該考慮到整個查詢。其實mysql可以使用索引來直接獲取列的數據。如果索引的葉子節點包含了要查詢的數據,那么就不用回表查詢了,也就是說這種索引包含(亦稱覆蓋)所有需要查詢的字段的值,我們稱這種索引為覆蓋索引。

注:引入數據表t_user,插入約1千萬條記錄,用作下文例子使用。

1工欲善其事,必先利其器

        explain命令是查看查詢優化器如何決定執行查詢的主要方法。要使用此命令,只需要在select關鍵字之前添加這個命令即可。當執行查詢時,它會返回信息,顯示出執行計划中的每一部分和執行的次序,而並非真正執行這個查詢。如圖1.1所示,是執行explain的顯示結果,其中sql語句中的\G表示將輸出按列顯示:

圖1.1 explain顯示查詢執行計划

    當發起一個被索引覆蓋的查詢時,在explain的Extra列可以看到 Using index的標識。

 

2場景:查詢表中name列有值的記錄數

圖2.1 查詢name列有值的記錄數

 

圖2.2 執行計划

       如上圖2.1所示,其中查詢語句用SQL_NO_CACHE關鍵字來禁止緩存查詢結果。此查詢耗時6.43秒。從圖3的執行計划得知,type:ALL,表示MySQL掃描整張表,從頭到尾去找到需要的行。下面對此查詢列建立索引。

圖2.3 為name列建立索引

 

圖2.4 重新執行的查詢sql

圖2.5 重新查看執行計划

    如圖2.3所示,為name列建立索引之后,重新執行查詢。此時查詢耗時3.80秒,比未加索引提高了2.63秒。從圖2.5的查詢計划可知,type:index,這個跟全表掃描一樣,只是MySQL掃描表時按索引次序進行而不是行。但是看到Extra:Using index,說明MySQL正在使用覆蓋索引,它只掃描索引的數據,而不是按索引次序的每一行。它比按索引次序全表掃描的開銷少很多。

3分頁查詢email

圖3.1 分頁查詢email

圖3.2 分頁查詢執行計划

    從圖3.1可知,分頁查詢耗時53.99,如圖3.2所示,type:All,說明MySQL進行了全表掃描。下面在password和email列上創建聯合索引。

圖3.3 添加聯合索引

圖3.4 重新分頁查詢

圖3.5 重新執行查詢計划

如圖3.4所示,分頁查詢基本不耗時間。從圖3.5可知,Extra:Using index,MySQL使用了覆蓋索引進行查詢。查詢效率得到極大的提升。

4覆蓋索引總結

回想一下,如果查詢只需要掃描索引而無須回表,將帶來諸多好處。

(1)索引條目通常遠小於數據行大小,如果只讀取索引,MySQL就會極大地減少數據訪問量。

(2)索引按照列值順序存儲,對於I/O密集的范圍查詢會比隨機從磁盤中讀取每一行數據的I/O要少很多。

(3)InnoDB的輔助索引(亦稱二級索引)在葉子節點中保存了行的主鍵值,如果二級索引能夠覆蓋查詢,則可不必對主鍵索引進行二次查詢了。

    覆蓋索引就是從索引中直接獲取查詢結果,要使用覆蓋索引需要注意select查詢列中包含在索引列中;where條件包含索引列或者復合索引的前導列;查詢結果的字段長度盡可能少。

-------------------------------------------------------------------------------------------------
寫點代碼,寫點科技。
微信公眾號「軟件開發資訊」,遇見了不妨就關注看看。


免責聲明!

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



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