在 innodb 中,從二級索引回到主鍵索引查詢資料,這個過程稱作回表過程,而且這個回表過程是可以被優化的,這個優化就是利用覆蓋索引。
先說結論,如果乙個索引的字段包含了所有要查詢的字段,這個索引就稱作覆蓋索引,覆蓋索引可以減少回表過程,能有效提高查詢效率。
前面我們有說過,在 innodb 中資料都是儲存在 b+ 樹上,主鍵索引儲存了整行記錄,二級索引儲存了主鍵的值。
一次查詢操作,要麼是遍歷主鍵索引,要麼是遍歷二級索引,要麼就是先遍歷二級索引得到主鍵 id 的值,然後再到主鍵索引上通過主鍵 id 查詢滿足要求的記錄。
如果只遍歷一次 b+ 樹就能獲取到我們要的資料,即沒有回表過程,這個效率顯然是不錯的,這就是覆蓋索引的優勢。下面看個具體的例子。
mysql> create table user(
id int(11) primary key,
name varchar(20) not null,
age int(11),
*** int(11),
index (age)) engine=innodb;
依然是新建乙個表,建立索引,插入一些測試資料,注意這裡只是為了解釋說明覆蓋索引,並不表示 mysql 的真實執行方式,因為會涉及到 mysql 的優化器機制,這裡暫且不說了,以後再寫。
1 bob 16 1
2 kom 19 0
3 gum 18 1
4 tt 20 1
5 yy 25 1
建立乙個 user 表,給 age 字段新增乙個二級索引,並插入上面五條資料,然後看下面這條查詢語句。
select name from user where age between 18 and 21
我們來分析下這條 sql 的執行過程:
1、age 欄位上有索引,mysql 會先到 age 欄位的 b+ 樹上找到滿足條件的第乙個葉子節點(age=19),這個葉子節點上儲存了對應主鍵 id 的值 2,然後再到主鍵索引上找到 id 為 2 的這條記錄,同時把 name 欄位拿出來。
2、重複第一步的操作,繼續從 age 索引上的葉子節點往後遍歷找出滿足條件的第二個葉子節點,同樣回到主鍵上拿出 name 欄位的值,直到遍歷到不滿足條件的葉子節點(age=25)。
也就是說,這條 sql 語句雖然用到了索引,但是 age 索引上並沒有要查詢的 name 字段,所以只能回表到主鍵索引上查出 name 字段,所以這個過程其實是遍歷了個兩個 b+ 樹。
那麼我們刪除 age 這個單列索引,建立乙個覆蓋索引 (age,name), 把要查詢的 name 欄位也新增到索引中來。
#刪除原索引
drop index age on user
#新建覆蓋索引
alter table user add index age_name(age,name)
由於現在這個覆蓋索引上的字段包含了要查詢的 age 和 name 字段,免去了到主鍵索引上查詢資料的過程,其實也就是只遍歷了乙個 b+ 樹,可以大大提公升查詢效率。
新增索引雖然能提公升查詢效率,但索引也是需要占用額外空間的,而且索引還需要維護成本,所以通常加不加索引需要根據實際需求來權衡。
總之,在設計索引或者優化 sql 語句的時候,要盡量避免回表操作,所以使用覆蓋索引是一種常用的 sql 優化手段。
所以我們平時寫 sql 語句的時候,select 後面只寫查詢需要用到的字段,去掉不需要的字段,避免回表操作。
簡單12招讓Hive執行快一點,再快一點
hive可以讓你在hadoop上使用sql,但是在分布系統上的sql的調優是不同的。這裡有12個技巧能夠幫助你。hive並不是乙個關係型資料庫,但它假裝是大部分情況中的乙個。它有 執行sql,並且支援jdbc和odbc。這個啟示有利及不利的訊息 hive不執行查詢資料庫方式。這是乙個很長的故事,但是...
效能優化 讓nodejs再快一點
本文首次發表於但從node.js 服務端 的角度來看,js本身的執行時間卻變得至關重要,還是之前的例子,如果執行時間從30ms降到3ms,理論上qps就能提公升10倍,換句話說,以前要10臺伺服器才能扛住的流量現在1臺伺服器就能扛住,而且響應時間更短.那到底node端如何做效能優化呢?有兩種方法,一...
關於如何快一點提高Python功力
關於如何快一點提高python功力 確實當你學了python的一段時間之後會有一陣不知道如何更快的提高自己的功力。其實python也是語言的一種,雖然語法很簡單,但是內涵真的很豐富,招式非常的多。修煉武功我個人覺得分幾個層次 第一招是語法 算是基本功,熟悉一門語言,語法是最核心也是最基礎的,你必須要...