前段時間有讀者提議講講索引下推,這期就把這事兒安排上。多餘的前言就不贅述了,我們直接開始。
列位坐好!
圖注:思維導圖
回表操作
對於資料庫來說,只要涉及到索引,必然繞不過去回表操作。當然這也是我們今天所講內容的前調基礎。
說到回表,我們需要從索引開始說起。別擔心,不會長篇大論,這裡只是簡單講下主鍵索引與普通索引,目的是讓大家對回表操作有個認識。如果你對回表操作很熟悉了,那麼可以跳過這一段。
這裡我們只以 Innodb 儲存引擎作為講解物件。
主鍵索引
主鍵索引在底層的資料儲存是通過 B+ 樹來實現的。簡單來說,就是除葉子節之外的其他節點都儲存的是主鍵值。而葉子節點上儲存的是整行的資料。
大體結構如下圖所示。
非主鍵索引
除了主鍵索引外,其它的索引都被稱為非主鍵索引。與主鍵索引不同的是,非主鍵索引的葉子節點上儲存的是主鍵的值。
那讓我們再回到開始的問題,什麼是回表操作?
當我們在非主鍵索引上查詢一行資料的時候,此時的查詢方式是先搜尋非主鍵索引樹,拿到對應的主鍵值,再到主鍵索引樹上查詢對應的行資料。
這種操作就叫作回表操作。
好了,這裡你應該瞭解了什麼是回表操作了。簡單來講,就是在非主鍵索引樹上拿到對應的主鍵值,然後回到主鍵索引上找到對應的行資料。
這樣做的前提條件是,所要查詢的欄位不存在於非主鍵索引樹上。
低版本操作
講完了回表操作,讓我們繼續回到這篇文章的主題——索引下推。
其實在 Mysql 5.6 版本之前是沒有索引下推這個功能的,從 5.6 版本後才加上了這個優化項。所以在引出索引下推前還是先回顧下沒有這個功能時是怎樣一種處理方式。
我們以一個真例項子來進行講解。
在這裡有張使用者表 user,記錄著使用者的姓名,性別,身高,年齡等資訊。表中 id 是自增主鍵,(name,sex) 是聯合索引。在這裡用 1 表示男,2 表示女。現在需要查詢所有姓王的男性資訊。
SQL 實現起來很簡單:
但是它的實現原理是什麼呢?
根據聯合索引最左字首原則,我們在非主鍵索引樹上找到第一個滿足條件的值時,通過葉子節點記錄的主鍵值再回到主鍵索引樹上查詢到對應的行資料,再對比是否為當前所要查詢的性別。
整個原理可以用下邊的圖進行表示。
看到了吧,低版本中需要每條資料都進行回表,增加了樹的搜尋次數。如果遇到所要查詢的資料量很大的話,效能必然有所缺失。
高版本操作
講完了低版本操作,讓我們繼續回到這篇文章的主題——索引下推。
知道了痛點,那麼怎麼解決。很簡單,只有符合條件了再進行回表。結合我們的例子來說就是當滿足了性別 sex = 1 了,再回表查詢。這樣原本可能需要進行回表查詢 4 次,現在可能只需要 2 次就可以了。
所以本質來說,索引下推就是隻有符合條件再進行回表,對索引中包含的欄位先進行判斷,不符合條件的跳過。減少了不必要的回表操作。
總結
回表操作
-
當所要查詢的欄位不在非主鍵索引樹上時,需要通過葉子節點的主鍵值去主鍵索引上獲取對應的行資料,這個過程稱為回表操作。
索引下推
-
索引下推主要是減少了不必要的回表操作。對於查詢出來的資料,先過濾掉不符合條件的,其餘的再去主鍵索引樹上查詢。
關於作者
作者:大家好,我是萊烏,BAT搬磚工一枚。從小公司進入大廠,一路走來收穫良多,想將這些經驗分享給有需要的人,因此建立了公眾號【IT界農民工】。定時更新,希望能幫助到你。同時,我給大家肝了一份Redis面經手冊,在我的公眾號內回覆【pdf】即可獲取,希望對你有所幫助。
往期內容:
漫畫系列:
MySQL系列:
Redis系列: