前段時間看了一下數據庫相關知識,出現了索引下推這個名詞,有必要記錄下來作為知識儲備。索引下推用一句話總結是:索引下推是數據庫檢索數據過程中為減少回表次數而做的優化。
首先介紹下什么是數據庫回表,回表是一種數據庫檢索過程。通常發生在使用二級索引檢索非主索引數據的過程中。舉個例子:
usertest數據表
假設有上面一張表,上面的ID字段是主鍵索引,age是普通索引。
對比下面兩條SQL語句:
select id from usertest where age = 10;
select name from usertest where age = 10;
第一條SQL語句不會產生回表(暫時不清楚不要緊):普通索引存儲的值是主鍵的值。也就是說age索引里面存儲的結構是下面的情況:
age索引
根據age查詢id的時候,索引中的值完全可以覆蓋查詢結果集字段時,不會產生回表(暫時不清楚還不要緊)操作。
由此也可以看出第二條SQL語句會產生回表是因為查詢的結果集無法通過索引中的值直接獲取。需要根據age查詢到的id值再回到主鍵索引里面再次查詢,這個過程叫做回表。
然后再看索引下推
還是上面的usertest表,只是索引變了,ID字段是仍主鍵索引,但是我們加上一個復合索引name_age(name,age)。
執行下面一條SQL語句:
select * from usertest where name like 'a%' and age = 10;
在MySQL5.6之前的執行流程大概是這樣的:
1.根據最左前綴原則,執行name like 'a%'可以快速檢索出id的值為1,5。
name like 'a%'查詢結果
2.然后根據id的值進行回表操作,再次進行過濾age=10的數據。
查詢id=1回表1次,id=5回表1次,這個過程總共回表了2次。
可能到這里都會有疑問,為什么不在索引里面直接過濾age=10的數據,因為復合索引里面也存了age的數據,這樣明明可以減少回表1次?恭喜啦,MySQL5.6以后就這么做了,這就是索引下推。
可以看出,索引下推具體是在復合索引的查詢中,針對特定的過濾條件而進行減少回表次數而做的優化(個人覺得本來就該這么設計的)。