Grapemysql
今天在跑腳本的時候發現了幾條慢查詢,根據以前的經驗實屬不該該,後來通過查找資料和分析出來結果,在這裏簡單記錄一下。算法
首先,個人sql是這個樣子:sql
select `id` from `xxx` force index(idx_d_t) where `date` = '2019-09-11' AND `time_flag` < '20190911220000' order by id asc;
索引是下邊這個樣子:優化
KEY `inx_t_d` (`date`,`time_flag`);
按照我以前的理解這條sql是能夠走這個索引的,可是他沒有,他選擇了主鍵索引。spa
看到這是個慢查詢,我起手一個explain,結果以下:指針
看到這個結果我確定不服啊,爲何是走的主鍵索引,所以開始了百度谷歌之旅。
剛開始我找到了一個自認爲比較正確的方法,在某度上找了一篇文章說orderby以前有範圍查找的會走orderby以後的索引,反之走orderby以前的索引,我試了一下,哎,不錯,我把範圍查詢改爲了等值查詢,是走了個人索引了,可是我看了一眼行數,一臉懵逼,爲何這麼多行?這不是我想要的code
而後我profiling(你們能夠自行百度)查了下時間,發現Creating sort index這哥們佔用了九成的時間,這時候我敏銳的察覺到了這個排序有問題,(該吃飯了)不行,繼續查!
繼續查,上某哥,哎你別說,某哥大法仍是好,終於找到了一個大佬的分析,具體是什麼緣由呢?blog
首次,我強制走個人聯合索引看下狀況:排序
看到上圖會發現有個差異就是Using filesort這玩意兒,這玩意兒是個什麼東西呢?簡單的說filesort 是經過相應的排序算法將取得的數據在內存中進行排序。俗話說有對比才有傷害,抓到敵人的小辮子就接近了勝利,咱們繼續看。索引
fliesort有兩種排序方式:
何時用到這兩種呢?MySQL 主要經過比較所設定的系統參數 max_length_for_sort_data 的大小和 Query 語句所取出的字段類型大小總和來斷定須要使用哪種排序算法。若是 max_length_for_sort_data 更大,則使用第二種優化後的算法,反之使用第一種算法。很顯然應該儘量讓 MySQL 選擇使用第二種單路算法來進行排序。這樣能夠減小大量的隨機 IO 操做,很大幅度地提升排序工做的效率。
上文分析的排序時間過長極可能就和這個有關係了,繼續查資料分析,問題的關鍵就在於爲何會filesort。
在執行語句的時候,由於數據量較大,MySQL優化器認爲走聯合索引很差,默認選擇了第一個更慢的執行計劃,它的理由是走主鍵索引不須要內存排序,候選的 idx_d_t被淘汰。優化器認爲主鍵索引不用排序比聯合索引要好,因此致使了這種狀況,
那咱們該怎麼作,在這裏我只列出個人解決方法,他認爲主鍵更好,那麼咱們就給他更好的,咱們更改idx_d_t這個索引,由date,time_flag改爲,id,date,time_flag,這樣就解決問題了。
如圖:
最後總結一下,就是優化器會盡可能避免走file_sort,這樣可能會致使一些問題。
以上分析如有差錯,還望不吝指教!感謝。
參考文章: