今天上班發現線上機器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內核,看看能否找到問題的答案。