SQL優化 MySQL版 - 多表優化及細節詳講


多表優化及細節詳講

作者 : Stanley 羅昊

轉載請注明出處和署名,謝謝!

注:本文章需要MySQL數據庫優化基礎或觀看前幾篇文章,傳送門:

B樹索引詳講(初識SQL優化,認識索引):https://www.cnblogs.com/StanleyBlogs/p/10413349.html

B樹索引進階(索引分類、創建方式、刪除索引、查看索引、SQL性能問題):https://www.cnblogs.com/StanleyBlogs/p/10416865.html

SQL執行計划於笛卡爾積(了解什么是SQL執行計划,優化原理):https://www.cnblogs.com/StanleyBlogs/p/10422202.html

Type詳講(理解優化級別):https://www.cnblogs.com/StanleyBlogs/p/10426385.html

Extra(理解最終優化概念):https://www.cnblogs.com/StanleyBlogs/p/10429969.html

單表優化(開啟優化篇章):https://www.cnblogs.com/StanleyBlogs/p/10442557.html

優化准備

首先我們需要有一個數據庫,coursedb,分別創建course(課程表)、teacher(老師表),有以下字段,我們接下來將用以下這張表來做優化實例;

teacher表里面的id 是代表一號老師教2號課程2號老師教1號課程3號老師教三號課程;id是主鍵

course表就是課程表1號代表java課程2號代表python...cid是主鍵

多表優化

此次教程不再使用可視化工具,因為效率太慢,我還是比較喜歡命令行操作;

現在有表了,有數據了,我現在寫一個左連接,二表關聯寫一個左連接:

select * from teacher t left outer join course c on t.cid = c.cid where c.cnourse

左連接詳解:

left join 是left outer join的簡寫【本語句使用left outer join】,它的全稱是左外連接,是外連接中的一種。

左(外)連接,左表(teacher)的記錄將會全部表示出來,而右表(cnourse)只會顯示符合搜索條件的記錄。右表記錄不足的地方均為NULL

語句解釋:現在我們需要兩表合一,所以就用左連接的方式,on則表明連接條件,where后面則是查詢條件,查詢cnourse = java課程的數據;

執行結果:

現在,我們就根據以上sql語句進行優化,所謂的優化,那就是加索引,在加索引之前,我們需要考慮一些問題;

對於這個問題,我有一個結論,就是小表驅動大表,什么意思呢?我舉個例子:

比方說我現在有一個where 小表.x = 大表.y;這個就被稱之為小表驅動大表,就是把小表放左邊大表放一邊,這是一個結論,咱們可以稍微分析一下為啥這樣干;

假設小表里面有10條數據,我大表里面有300條數據,小表放左邊大表放右邊對於表里的每10條數據里的每一條,300條數據都會輪循遍歷一次,10條里面第一條拿出來,右邊執行300次,左邊10條第二條拿出來,右邊再300次,同理,第三條出來,再300次....;

有一個編程原則我在這里說一下,在寫for循環的時候,雙層for循環,你外層數據越小內存數據越大,那它的性能就越高,這個是編程原則,把這個原則放到這里也是一樣的,數據量最小的表放在前面,數據量最大的表放在后面(where 小表 cid= 大表 cid)

但是對於剛才我寫的sql語句來說,t.cid = c.cid即便反過來查詢結果也是一樣的完全是等價寫法僅從結果上來看,但是我們從這個性能上來看,你在寫之前分析一下到底是t表數據小呢,還是c表數據小,將數據小的表放到左邊;

本題因為都是三條數據,所以不影響,再此就是提一提;

連表查詢添加索引原則

現在我們再來研究,我們的索引到底加給那個字段;

在這里我需要再提一下,索引一定要建立經常使用的字段上,這句話對於本次優化應該這么理解:

對於左邊這個小表.x = 10,每一條我都要執行300次,因此左邊這個表的使用量比較大,因為每用一次執行300次嘛,左邊這個x字段使用頻率比較高,因此我們就需要給這個x字段加索引

所以呢?本次優化 t.cid = c.cid很明顯,t.cid使用最為頻繁,所以給該字段加索引,值得一提的是,因為本次sql語句是左外連接,對於左外連接來說,一般情況下給左邊加索引,因為是左外嘛,左邊剛好是小表,同理,如果是右外連接我們就需要給右表加索引;

其實很好理解,左外連接就是以左表為基准,意思就是左表的所有數據都要匹配,你全部要匹配,那你必然使用頻繁,因此給左表加,右外連接以右表為基准,你右表使用頻繁,那就給右表加索引,都是一個意思

添加索引

分析完了,接下來就開始我們的優化吧;

在優化之前,我們先查詢一下原生態SQL語句的執行情況,我們需要explain,就是查看一下不加索引的情況:

explain select * from teacher t left outer join course c on t.cid = c.cid where c.cnourse = "java"

執行結果:

很顯然,級別都是ALL,也出現了Using where;

我們現在開始加索引:

alter table teacher add index index_teacher_cid(cid);

加完索引再試試:

我們能發現,有一張表點查詢級別提到了index,其次,我們后面還增加了一個Using index索引覆蓋提高了查詢性能;

到這里,我們是不是少加一個索引,我們把SQL語句拿過來看看:

select * from teacher t left outer join course c on t.cid = c.cid where c.cnourse = "java"

查詢條件必然是索引才對,因為要根據它去查數據,所以我漏加了一個,現在我加上后再去執行:

alter table course add index index_course_cnourse(cnourse);

加完索引再去執行試試:

首先,查詢級別全部提升到fef級別,其次在查看生效的索引,兩個索引被檢測到了,在最終效能里面出現了兩個Using index因為兩章表,此條語句優化完成;

Using join buffer

在Extra字段里面出現了一個在前幾章都沒有見過的屬性,我們來了解一下它:

出現它的原因:MySQL引擎使用了連接緩存;

詳解:

說白了就是你這個SQL語句寫的太差了,mysql看不下去了它給你加了一個連接緩存,出現這個就說明mysql底層動你的sql語句了,給你加了個緩存;

后面我們自主優化性能提升后,mysql覺得我寫的還不錯,就不給我加緩存了;

多表查詢技巧

剛才我們介紹了兩表查詢,有些人就會問,那三張表呢?其實我告訴你,100張表也是一樣的.....即便你100張表連表查詢,原則也是不變的,因為沒有新知識了,所以在這里我就說下多表查詢的技巧;

1.有多張表,如果你要優化,首先第一個原則我在上面介紹過,小表驅動大表,那個表數據少,就把它寫到等號的左邊,即便查詢結果一樣,就比如a表數據少b表數據多,我們就 where a.id= b.id;

2.如果有多張表,索引就建立在經常查詢的字段上,假設你有 a b c 三張表,一共有20個字段,這個20個字段你沒有必要全加,看着三張表的20個字段里面,誰經常在查詢,誰在where后面,以及一些常用字段;

今日感悟:

永遠不要強力的去反對別人;

海格斯效應告訴我們:

           當你反對別人時,得到的,將是更加強力的反對;

舉例說明:

          你剝奪了孩子玩耍的時間,那么孩子多半會把學習成績降下來了給你看;

          你剝奪了妻自由的空間,她也會什么家務都不干,你也休想安寧;

嘗試用哪個另一個角度去解決問題,否則一定會面臨任性的通病;

               你跟我過不去,我也讓你不痛快!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM