mysql选择索引逻辑_Mysql索引选择逻辑
有時候我們會發(fā)現(xiàn)mysql可能出現(xiàn)選錯索引的情況,要了解這個問題我們得先看看sql優(yōu)化器是怎么選擇索引的
索引選擇邏輯
優(yōu)化器選擇索引的目的,是找到一個最優(yōu)的執(zhí)行方案,并用最小的代價去執(zhí)行語句。在數(shù)據(jù)庫里面,掃描行數(shù)是影響執(zhí)行代價的因素之一。掃描的行數(shù)越少,意味著訪問磁盤數(shù)據(jù)的次數(shù)越少,消耗的 CPU 資源越少
掃描行數(shù)是怎么判斷的?
MySQL 在真正開始執(zhí)行語句之前,并不能精確地知道滿足這個條件的記錄有多少條,而只能根據(jù)統(tǒng)計信息來估算記錄數(shù)
這個統(tǒng)計信息就是索引的“區(qū)分度”。顯然,一個索引上不同的值越多,這個索引的區(qū)分度就越好。而一個索引上不同的值的個數(shù),我們稱之為“基數(shù)”。也就是說,這個基數(shù)越大,索引的區(qū)分度越好
MySQL 是怎樣得到索引的基數(shù)的呢
采樣統(tǒng)計的時候,InnoDB 默認會選擇 N 個數(shù)據(jù)頁,統(tǒng)計這些頁面上的不同值,得到一個平均值,然后乘以這個索引的頁面數(shù),就得到了這個索引的基數(shù)
而數(shù)據(jù)表是會持續(xù)更新的,索引統(tǒng)計信息也不會固定不變。所以,當(dāng)變更的數(shù)據(jù)行數(shù)超過 1/M 的時候,會自動觸發(fā)重新做一次索引統(tǒng)計
在 MySQL 中,有兩種存儲索引統(tǒng)計的方式,可以通過設(shè)置參數(shù) innodb_stats_persistent 的值來選擇: 設(shè)置為 on 的時候,表示統(tǒng)計信息會持久化存儲。這時,默認的 N 是 20,M 是 10。 設(shè)置為 off 的時候,表示統(tǒng)計信息只存儲在內(nèi)存中。這時,默認的 N 是 8,M 是 16
由于是采樣統(tǒng)計,所以不管 N 是 20 還是 8,這個基數(shù)都是很容易不準(zhǔn)的。
其實索引統(tǒng)計只是一個輸入,對于一個具體的語句來說,優(yōu)化器還要判斷,執(zhí)行這個語句本身要掃描多少行
如果使用索引,每次從索引上拿到一個值,都要回到主鍵索引上查出整行數(shù)據(jù),這個代價優(yōu)化器也要算進去的
MySQL 選錯索引,主要還是沒能準(zhǔn)確地判斷出掃描行數(shù)
既然是統(tǒng)計信息不對,那就修正。analyze table t 命令,可以用來重新統(tǒng)計索引信息
索引選擇異常和處理
當(dāng)然,掃描行數(shù)并不是唯一的判斷標(biāo)準(zhǔn),優(yōu)化器還會結(jié)合是否使用臨時表、是否排序等因素進行綜合判斷 即使統(tǒng)計信息沒錯依然可能出現(xiàn)選錯的情況,那我們應(yīng)該如何處理吶?
第一種方法是,采用 force index 強行選擇一個索引
第二種方法就是,我們可以考慮修改語句,引導(dǎo) MySQL 使用我們期望的索引
第三種方法是,在有些場景下,我們可以新建一個更合適的索引,來提供給優(yōu)化器做選 擇,或刪掉誤用的索引
總結(jié)
以上是生活随笔為你收集整理的mysql选择索引逻辑_Mysql索引选择逻辑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python torch库_python
- 下一篇: mysql 统计 邮箱_mysql查询之