34 | 到底可不可以使用join?

在實際生產中,關于 join 語句使用的問題,一般會集中在以下兩類:

我們 DBA 不讓使用 join,使用 join 有什么問題呢?

如果有兩個大小不同的表做 join,應該用哪個表做驅動表呢?


第一個問題:能不能使用 join 語句?

如果可以使用 Index Nested-Loop Join 算法,也就是說可以用上被驅動表上的索引,其實是沒問題的;

如果使用 Block Nested-Loop Join 算法,掃描行數(shù)就會過多。尤其是在大表上的 join 操作,這樣可能要掃描被驅動表很多次,會占用大量的系統(tǒng)資源。所以這種 join 盡量不要用。

所以你在判斷要不要使用 join 語句時,就是看 explain 結果里面,Extra 字段里面有沒有出現(xiàn)“Block Nested Loop”字樣。

第二個問題是:如果要使用 join,應該選擇大表做驅動表還是選擇小表做驅動表?

如果是 Index Nested-Loop Join 算法,應該選擇小表做驅動表;

如果是 Block Nested-Loop Join 算法:

在 join_buffer_size 足夠大的時候,是一樣的;

在 join_buffer_size 不夠大的時候(這種情況更常見),應該選擇小表做驅動表。

所以,這個問題的結論就是,總是應該使用小表做驅動表。

案例:

1)優(yōu)化前的sql語句以channels_news為第一個關聯(lián)表,找到161590條記錄;

2)優(yōu)化后的sql語句以news表為第一關聯(lián)表,找到255440條記錄,比第一條sql語句查找多了9W多條。因此,優(yōu)化前的sql語句的關聯(lián)順序是MySQL優(yōu)化器的選擇,可以讓查詢進行更小的嵌套循環(huán)和回溯操作。MySQL通過選擇合適的關聯(lián)順序來讓查詢執(zhí)行的成本盡可能低,重新定義關聯(lián)的順序是優(yōu)化器很重要的一部分功能。不過有時候,優(yōu)化器給出的并不是最優(yōu)的關聯(lián)順序。這時可以使用STRAIGHT_JOIN關鍵字重寫查詢,讓優(yōu)化器按照你認為的最優(yōu)關聯(lián)順序執(zhí)行。

造成這次sql語句查詢耗時5s的原因是,sql語句order by的字段不在mysql的優(yōu)化器選在驅動表上,所以導致這次關聯(lián)查詢排序字段上的索引沒有被使用。因此,通過使用STRAIGHT_JOIN來強制制定關聯(lián)查詢的表順序,以達到優(yōu)化的目的。但是,有時候我們人為地指定順序不一定比mysql的優(yōu)化引擎準確,所以在使用STRAIGHT_JOIN的時候三思而后行



感謝極客時間:https://time.geekbang.org/column/article/79700

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。