一次很是有意思的 SQL 優化經歷: 從 30248.271s 到 0.001s

個人公衆號: MarkerHub,Java網站: https://markerhub.com

更多精選文章請點擊:Java筆記大全.mdhtml

小Hub領讀:

數據量少的時候看不出區別,量大差異明顯,文末的4點總結你應該去看一下,或許對你有幫助!java


場景

用的數據庫是 mysql5.6,下面簡單的介紹下場景mysql

課程表:git

數據 100 條github

學生表:sql

數據 70000 條數據庫

學生成績表 SC:優化

數據 70w 條網站

查詢目的:spa

查找語文考 100 分的考生

查詢語句:

執行時間:30248.271s

爲何這麼慢?先來查看下查詢計劃:

發現沒有用到索引,type 全是 ALL,那麼首先想到的就是創建一個索引,創建索引的字段固然是在 where 條件的字段。

先給 sc 表的 c_id 和 score 建個索引

再次執行上述查詢語句,時間爲: 1.054s

快了 3w 多倍,大大縮短了查詢時間,看來索引能極大程度的提升查詢效率,看來建索引頗有必要,不少時候都忘記建索引了,數據量小的的時候壓根沒感受,這優化感受挺爽。

可是 1s 的時間仍是太長了,還能進行優化嗎,仔細看執行計劃:

查看優化後的 sql:

補充:這裏有網友問怎麼查看優化後的語句

方法以下:

在命令窗口執行

有 type=all

按照我以前的想法,該 sql 的執行的順序應該是先執行子查詢

耗時:0.001s

獲得以下結果:

而後再執行

耗時:0.001s

這樣就是至關快了啊,Mysql 居然不是先執行裏層的查詢,而是將 sql 優化成了 exists 子句,並出現了 EPENDENT SUBQUERY,

mysql 是先執行外層查詢,再執行裏層的查詢,這樣就要循環 70007*11=770077 次。

那麼改用鏈接查詢呢?

這裏爲了從新分析鏈接查詢的狀況,先暫時刪除索引 sc_c_id_index,sc_score_index

執行時間是:0.057s

效率有所提升,看看執行計劃:

這裏有連表的狀況出現,我猜測是否是要給 sc 表的 s_id 創建個索引

CREATE index sc_s_id_index on SC(s_id);

show index from SC

在執行鏈接查詢

時間: 1.076s,居然時間還變長了,什麼緣由?查看執行計劃:

優化後的查詢語句爲:

貌似是先作的鏈接查詢,再執行的 where 過濾

回到前面的執行計劃:

這裏是先作的 where 過濾,再作連表,執行計劃還不是固定的,那麼咱們先看下標準的 sql 執行順序:

正常狀況下是先 join 再 where 過濾,可是咱們這裏的狀況,若是先 join,將會有 70w 條數據發送 join 作操,所以先執行 where

過濾是明智方案,如今爲了排除 mysql 的查詢優化,我本身寫一條優化後的 sql

即先執行 sc 表的過濾,再進行錶鏈接,執行時間爲:0.054s

和以前沒有建 s_id 索引的時間差很少

查看執行計劃:

先提取 sc 再連表,這樣效率就高多了,如今的問題是提取 sc 的時候出現了掃描表,那麼如今能夠明確須要創建相關索引

再執行查詢:

執行時間爲:0.001s,這個時間至關靠譜,快了 50 倍

執行計劃:

咱們會看到,先提取 sc,再連表,都用到了索引。

那麼再來執行下 sql

執行時間 0.001s

執行計劃:

這裏是 mysql 進行了查詢語句優化,先執行了 where 過濾,再執行鏈接操做,且都用到了索引。

總結

一、mysql 嵌套子查詢效率確實比較低

二、能夠將其優化成鏈接查詢

三、創建合適的索引

四、學會分析 sql 執行計劃,mysql 會對 sql 進行優化,因此分析執行計劃很重要

推薦閱讀

Java筆記大全.md

太讚了,這個Java網站,什麼項目都有!https://markerhub.com

這個B站的UP主,講的java真不錯!

相關文章
相關標籤/搜索