個人公衆號: MarkerHub,Java網站: https://markerhub.com更多精選文章請點擊:Java筆記大全.mdhtml
數據量少的時候看不出區別,量大差異明顯,文末的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 進行優化,因此分析執行計劃很重要