MySQL索引選擇問題

  在進行數據查詢的時候,MySQL優化器會自動爲查詢語句選擇合適的索引,索引選擇的正確與否對MySQL的執行速度有很大影響。使用explain語句可以查詢得到執行計劃的詳細內容,而優化器選擇索引的目的,是找到一個最優的執行方案,並用最小的代價去執行語句。在數據庫裏面,掃描行數是影響執行代價的因素之一。掃描的行數越少,意味着訪問磁盤數據的次數越少,消耗的CPU資源越少,當然除了掃描行數之外也有其他考慮因素,包括是否需要回表等。
  那麼MySQL怎麼在執行前預判掃描行數呢?首先一個索引上不同的值越多,這個索引的區分度就越好。而一個索引上不同的值的個數,我們稱之爲“基數”(cardinality)。也就是說,這個基數越大,索引的區分度越好,可以通過show index from t來查看索引的詳細信息。MySQL通過採樣的方式來估算每張表的基數,採樣統計的時候,InnoDB默認會選擇N個數據頁,統計這些頁面上的不同值,得到一個平均值,然後乘以這個索引的頁面數,就得到了這個索引的基數。而數據表是會持續更新的,索引統計信息也不會固定不變。所以,當變更的數據行數超過1/M的時候,會自動觸發重新做一次索引統計。
  在MySQL中,有兩種存儲索引統計的方式,可以通過設置參數innodb_stats_persistent的值來選擇:

  設置爲on的時候,表示統計信息會持久化存儲。這時,默認的N是20,M是10。
  設置爲off的時候,表示統計信息只存儲在內存中。這時,默認的N是8,M是16。
  可以看到無論是上面哪一種,對於數據量比較大的表來說,採樣的數量都很小,所以並不能保證統計的準確,如果你發現explain的結果預估的rows值跟實際情況差距比較大,可以用analyze table t來更新統計信息。

  當選錯索引時,可以採取的辦法有:

  1. 採用force index強行選擇一個索引
  2. 可以考慮修改語句,引導MySQL使用我們期望的索引
  3. 可以新建一個更合適的索引,來提供給優化器做選擇,或刪掉誤用的索引

MySQL實戰45講

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章