MySQL爲何有時候會選錯索引?

/*
mysql掃描行數是如何判斷的?
mysql在真正的執行語句以前是不知道掃描行數的,只能根據統計信息來估算記錄數
這個統計信息就是 區分度 ,顯然一個索引上不一樣的值越多,這個索引的區分度就越好,而一個索引上不一樣值的個數,咱們稱之爲 基數 ,也就是說這個基數越大,索引的區分度越好

咱們可使用 show index 方法,查看一個索引的基數,如: show index from t 查看t表的索引基數

那麼mysql是怎麼獲取基數的呢?(採樣統計)
爲何要採樣統計呢?由於一張表一行一行查出來精確統計,成本過高
採樣統計的時候,innodb是選擇n個數據頁,統計這些頁面上的不一樣值,取得一個平均數,而後乘以這個索引的頁數,就會的獲得這個索引的基數
數據表中的數據是隨時發生改變的因此這個基數也會改變因此,當變動的數據行數大於 1/M的時候會自動觸發從新作一次索引統計

在mysql中有兩種存儲索引統計的方式,能夠經過設置參數 innodb_stats_persistent的值來選擇
設置爲on的時候,表示統計信息會持久化存儲,這時N默認是20,M是10
設置爲OFF的時候,統計信息只存儲在內存中,這時N是8,M是16

因爲是採樣統計,因此N是 20 仍是8 ,這個基數都是很容易不許的

除了掃描行數的不許以外,還有優化器會選擇成本低的執行方式,成本低不僅是掃描行數少。
如:一張表有10萬條數據,id索引和a索引,使用id索引須要掃描10row  而經過a索引須要15000 row 可是,使用a索引這裏須要進行再一次的回表,優化器將這個成本也算進去了,而id是直接在id主鍵上進行的掃描,沒有額外的代價


統計信息不對 修正
analyze table 表名
若是經過explain 這個命令查看的row 和實際相差比較大,就可使用這個命令修正(從新採樣統計)


強制使用指定索引(  force index(索引名) )
select * from t force index(a) where a between 10000 and 20000;


索引選擇異常和處理
1.經過force index 強行使用指定索引
2.修改表結構,引導優化器使用咱們想要的索引
3,在合適的產景下能夠考慮添加一個合適的索引來使用

*/
相關文章
相關標籤/搜索