閱讀筆記-MySQL索引原理及慢查詢優化
1. mysql的索引的實現原理
讀文章弄清楚索引的數據結構b+樹及其查找過程
2. 建索引的幾大原則
1.最左前綴匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配 ,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。
2.=和in可以亂序 ,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式
3.儘量選擇區分度高的列作爲索引 ,區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條記錄
4.索引列不能參與計算,保持列”乾淨” ,比如from_unixtime(create_time) = ‘2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(‘2014-05-29’);
5.儘量的擴展索引,不要新建索引 。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可
3. 慢查詢優化基本步驟
- 先運行看看是否真的很慢,注意設置SQL_NO_CACHE
- where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起, 單表每個字段分別查詢,看哪個字段的區分度最高
- explain查看執行計劃,是否與1預期一致(從鎖定記錄較少的表開始查詢)
- order by limit 形式的sql語句讓排序的表優先查
- 瞭解業務方使用場景
- 加索引時參照建索引的幾大原則
- 觀察結果,不符合預期繼續從0分析
4. 簡單總結,方便記憶
- 索引左匹配等原則(從數據結構和查找算法理解)
- explain row 分析(列的區分度)
- 僅從語句下手不行就從業務下手分析
- 關於排序和分類 — mysql的nested loop機制
- 不要只針對具體case來優化,而忽略了更復雜的情況(需要更多的分析+測試)
5.理論要紮實,不要混日子
同樣是MySQL,可以用來支撐Google/FaceBook/Taobao應用, 但可能連你的個人網站都撐不住。 套用最近比較流行的話:”查詢容易,優化不易,且寫且珍惜!”
6. 其他
如果你不太理解區分度公式
select count(*),accurate_result from stage_poi group by accurate_result;
+----------+-----------------+
| count(*) | accurate_result |
+----------+-----------------+
| 1023 | -1 |
| 2114655 | 0 |
| 972815 | 1 |
+----------+-----------------+
只需要理解上面這個情況,accurate_result 所能過濾的數據很少, 加上索引也無法鎖定特別少量的數據。
參考
http://blog.jobbole.com/86594/
https://en.wikipedia.org/wiki/B%2B_tree