把生產(chǎn)中的慢SQL從6000ms,一番折騰后運行只要40ms

慢SQL報警

郵件接收到了慢SQL報警,一看時間嚇一跳,竟然將近26s,看看是什么妖魔鬼怪?

由于涉及到生產(chǎn),表名經(jīng)過處理,并不是真實表名。。。

com.alibaba.druid.filter.stat.StatFilter | slow sql 25116 millis. SELECT count(1) FROM result oqr INNER JOIN o_query oq ON oq.sid = oqr.query_id WHERE 1 = 1 and oqr.status = 1 and oq.type not in (2,6) AND oqr.create_time >= ? AND oqr.create_time <= ?["2019-09-11 00:00:01","2019-10-11 23:59:59"]

開始分析

執(zhí)行計劃

初看就是兩個表內(nèi)連接,那看一看執(zhí)行計劃吧。。。

平臺輸出執(zhí)行計劃格式有問題,湊合看吧。


原始SQL執(zhí)行計劃

有一個全表掃描,而且行數(shù)很多啊,難怪很慢!

生產(chǎn)環(huán)境通過頁面跳板的方式查詢數(shù)據(jù)庫,將這條SQL在頁面執(zhí)行的時候,第一次沒有查出結(jié)果,因為平臺有執(zhí)行時間限制(20s),也意味著這條SQL超過20s還沒有執(zhí)行處理結(jié)果。

后來又執(zhí)行了幾次,通過執(zhí)行記錄來看,平均時間在6000ms左右。

兩張表的索引情況

o_query表的索引情況

result表的索引情況

通過執(zhí)行計劃的行數(shù)來看,result表應(yīng)該是全表掃描了所有的記錄。

猜測是不是兩張表先篩選,再連接會更快呢

將SQL修改為如下

select count(1) from
              (select query_id from result oqr where oqr.create_time between '2019-09-11 00:00:01' AND '2019-10-11 23:59:59' and oqr.status = 1) oqrs
inner join (select sid from o_query oq where oq.create_time between '2019-09-11 00:00:01' AND '2019-10-11 23:59:59' and oq.type not in (2, 6)) oqs  where oqrs.query_id = oqs.sid;

查看執(zhí)行計劃吧

修改后的SQL執(zhí)行計劃

通過執(zhí)行計劃來看,盡管還是全表掃描,但是行數(shù)卻少了很多個量級啊!
通過在平臺執(zhí)行這個修改后的SQL,很快就執(zhí)行完了,執(zhí)行時間是40ms左右,這顯然已經(jīng)快很多很多了?。?!

為什么修改后的SQL能快這么多呢?

猜測應(yīng)該是跟兩張表連接查詢的執(zhí)行過程有關(guān)系,本人英語渣渣,從官網(wǎng)找到執(zhí)行順序的資料很難啊,從網(wǎng)上搜索資料,發(fā)現(xiàn)有很多網(wǎng)友講的沒法解釋。。

掘金小冊子:MySQL 是怎樣運行的:從根兒上理解 MySQL

MySQL是怎樣運行的:從根兒上理解MySQL

其中有一篇文章:兩個表的親密接觸 —— 連接的原理
關(guān)于兩表連接的執(zhí)行過程,能恰好解釋為什么修改后的SQL能快這么多了。。。

下圖是從博文中截的圖:


兩表連接的執(zhí)行過程

查看優(yōu)化修改后的SQL

通過explain extended查看優(yōu)化修改后的SQL如下:

select count(1) AS `count(1)` from `o_query` `oq` join `result` `oqr` where ((`oqr`.`status` = 1) and (`oq`.`sid` = `oqr`.`query_id`) and (`oqr`.`create_time` between '2019-09-11 00:00:01' and '2019-10-11 23:59:59') and (`oq`.`create_time` between '2019-09-11 00:00:01' and '2019-10-11 23:59:59') and (`oq`.`type` not in (2,6)))

最后的一點思考

對于這條SQL應(yīng)該還有優(yōu)化的空間

o_query表在 create_time 字段上也應(yīng)該創(chuàng)建上索引

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容