mysql學習筆記(五)索引(下)
表初始語句
mysql> create table T ( ID int primary key, k int NOT NULL DEFAULT 0, s varchar(16) NOT NULL DEFAULT '', index k(k)) engine=InnoDB; insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');
在表 T 中,執行 select * from T where k between 3 and 5 的執行過程如下:
在 k 索引樹上找到 k=3 的記錄,取得 ID = 300;
再到 ID 索引樹查到 ID=300 對應的 R3;
在 k 索引樹取下一個值 k=5,取得 ID=500;
再回到 ID 索引樹查到 ID=500 對應的 R4;
在 k 索引樹取下一個值 k=6,不滿足條件,迴圈結束。
在這個過程中,回到主鍵索引樹搜尋的過程,我們稱為回表。可以看到,這個查詢過程讀了 k 索引樹的 3 條記錄(步驟 1、3 和 5),回表了兩次(步驟 2 和 4)。
覆蓋索引
如果執行的語句是 select ID from T where k between 3 and 5,這時只需要查 ID 的值,而 ID 的值已經在 k 索引樹上了,因此可以直接提供查詢結果,不需要回表。也就是說,在這個查詢裡面,索引 k 已經“覆蓋了”我們的查詢需求,我們稱為覆蓋索引。
當然,索引欄位的維護總是有代價的。因此,在建立冗餘索引來支援覆蓋索引時就需要權衡考慮了。
最左字首原則
B+ 樹這種索引結構,可以利用索引的“最左字首”,來定位記錄。
只要滿足最左字首,就可以利用索引來加速檢索。這個最左字首可以是聯合索引的最左 N 個欄位,也可以是字串索引的最左 M 個字元。
如果安排聯合索引的位置?
第一原則,通過調整順序,可以少維護一個索引,那麼這個順序就是優先考慮的
考慮空間,例如 name 欄位是比 age 欄位大的 ,那我就建議你建立一個(name,age) 的聯合索引和一個 (age) 的單欄位索引。
索引下堆
在 MySQL 5.6 之前,只能從 ID3 開始一個個回表。到主鍵索引上找出資料行,再對比欄位值。
而 MySQL 5.6 引入的索引下推優化(index condition pushdown), 可以在索引遍歷過程中,對索引中包含的欄位先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數。