今天上班發現線上機器CPU告警,看了一下發現是mysqld一直佔用CPU處於滿負荷狀態,show processlist;一下,發現不少查詢在排序狀態,隨便拿了一條sql explain看了一下,以下圖:
注意到後面多了一個Using filesort; 這個的意思並非說要在磁盤上進行排序。由於mysql的排序方法主要分爲兩大類,一種是排序的字段是有索引的,由於索引是有序的,因此不須要另外排序,另外一種是排序的字段沒有索引,因此須要對結果進行排序,在這種狀況下才會如上圖所示顯示一個Using filesort表示這個查詢須要排序。而這裏奇怪的是,這個查詢的排序字段applydate是有索引的,並且看possible_keys這一欄也能夠看到這個索引在檢索的時候是可能用到的key。
Show index 確認是否有索引:
問題查到這裏開始有點不知所措了,內存問題也被排除了。而後考慮是不是max_length_for_sort_data, sort_buffer_size這個參數設置太小形成的,實際上後來想一想這個因素是能夠直接排除的,由於若是索引能夠用的話是不須要另外排序的。開始懷疑是不是索引不可用的問題了。因而冒險把索引重建了試試。一開始嘗試能不能用repair命令來修復索引,發現這個命令只適用於myisam引擎,因而只好刪除索引重建。160W+行,刪除一個索引耗時14min, 建立索引耗時19min,固然這個耗時不是絕對的,還要考慮機器CPU性能、負荷狀況、以及各參數設置等。
在刪除掉了索引還沒建立以前,我特意測試了一下同一條查詢在有老的索引和當前沒有這個關鍵索引的狀況下的查詢時間,刪除索引前耗時13s,刪除索引後耗時19s,能夠說是在同一個量級了,到這裏彷佛更能肯定索引實際上是不可用的。
等待19min後,重建索引成功,火燒眉毛的試着執行了同一條sql,耗時0.22s。瞬間那個激動的心情溢於言表。再次explain這條查詢,Using filesort也沒有了。至此問題算是解決了。可是疑惑仍是有不少,主要有如下幾點:
1.是什麼致使了索引不可用
2.如何肯定執行執行這條查詢的時候其實是否用到了索引(explain的參數都是預估的),可否實時看到sql執行的狀況。
對於第一個問題,看來還須要大量的學習,雖然知道索引是B+樹實現的,本身也能手寫一個B樹出來,可是mysql到底是如何經過這個B樹來加快查詢仍是不太明白。對於第二個問題,打算研究一下mysql內核,看看可否找到問題的答案。