mysql 索引選擇算法/原理詳解(rows估算)

本文章假設讀者已瞭解mysql的索引基礎知識,如b+樹,聚集索引,並對explain分析結果已瞭解。以下主要分析mysql的索引選擇原理及算法。

Mysql InnoDB的查詢一般基於explian所獲取的最小rows來選擇使用哪一個索引。Rows是一個estimate的值,其估計算法(規則)如下:

1.如果是select c from where a=***,a上有索引。Mysql大概率會使用a上的索引。其rows計算規則爲Rows = ((Records_PLeft +  Records_P1 + Records_P2 + ... + Records_P8 + Records_PRight)/10)*Page_Num。

每一頁的page_size可以通過innodb_index_stats表裏的stat_name字段的n_diff_pfx0?和size估算出。如果n_diff_pfx0?爲1000000,size爲2000,則每頁存儲500。如果a對應的記錄數在500*10=5000內,則此explian獲得的rows基本上比較精確,即通過10頁的採樣全部獲取。如果a對應的記錄數在5000以上,則rows不準確。參見https://lists.mysql.com/commits/115810https://www.cnblogs.com/LBSer/p/3333881.html

2.如果是select c from where a=*** order by c ,a和c上都有索引。大概率會走a上索引。因爲a的索引是精確查找(explain type 是 const或者ref),用c的索引則是全索引表掃描。

3.如果是select c from where a=*** order by c limit 1 ,a和c上都有索引。這時mysql第一步先用a索引估算出rows值 。然後第二步,嘗試再用c的索引來修正rows值:其算法是拿全表的總條數除以第一步算出來的rows,然後乘以limit的值。如全表有1000000條記錄,第一步估算出是rows是20000,則rows會變成(1000000/20000)* 1=50。50<20000,則用索引c。如果limit 2,則rows爲100,用索引c。一直到估算出來的值大於20000(limit 400左右),纔會選用a的索引。見https://bugs.mysql.com/bug.php?id=78325。這裏最有意思的是mysql是假設你查詢的記錄是均勻的分佈在索引表裏的,所以會有這樣算法。

4.如果是select c from where a=*** limit 1,則還是會走a索引,因爲mysql不會有上述的第二步。

 
Mysql 分析工具:Trace介紹:
分析explain整個過程。
set global optimizer_trace='enabled=on';
select c from where a=*** order by c limit 1
select * from information_schema.optimizer_trace;可以分析上步整個trace過程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章