MySQL的JOIN(三):JOIN優化實踐之內循環的次數


這篇博文講述如何優化內循環的次數。內循環的次數受驅動表的記錄數所影響,驅動表記錄數越多,內循環就越多,連接效率就越低下,所以盡量用小表驅動大表。先插入測試數據。

    CREATE TABLE t1 (
        id INT PRIMARY KEY AUTO_INCREMENT,
        type INT
    );
    SELECT COUNT(*) FROM t1;
    +----------+
    | COUNT(*) |
    +----------+
    |    10000 |
    +----------+
    CREATE TABLE t2 (
        id INT PRIMARY KEY AUTO_INCREMENT,
        type INT
    );
    SELECT COUNT(*) FROM t2;
    +----------+
    | COUNT(*) |
    +----------+
    |      100 |
    +----------+

內連接誰當驅動表

實際業務場景中,左連接、右連接可以根據業務需求認定誰是驅動表,誰是被驅動表。但是內連接不同,根據嵌套循環算法的思想,t1內連接t2和t2內連接t1所得結果集是相同的。那么到底是誰連接誰呢?謹記一句話即可,小表驅動大表可以減小內循環的次數。下面用        STRAIGHT_JOIN強制左表連接右表。By the way,STRIGHT_JOIN比較冷門,在這里解釋下,其作用相當於內連接,不過強制規定了左表驅動右邊。詳情看這MySQL的JOIN(一):用法

    EXPLAIN SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.type=t2.type;
    +----+-------+------+------+-------+----------------------------------------------------+
    | id | table | type | key  | rows  | Extra                                              |
    +----+-------+------+------+-------+----------------------------------------------------+
    |  1 | t1    | ALL  | NULL | 10000 | NULL                                               |
    |  1 | t2    | ALL  | NULL |   100 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------+------+------+-------+----------------------------------------------------+
    EXPLAIN SELECT * FROM t2 STRAIGHT_JOIN t1 ON t2.type=t1.type;
    +----+-------+------+------+-------+----------------------------------------------------+
    | id | table | type | key  | rows  | Extra                                              |
    +----+-------+------+------+-------+----------------------------------------------------+
    |  1 | t2    | ALL  | NULL |   100 | NULL                                               |
    |  1 | t1    | ALL  | NULL | 10000 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------+------+------+-------+----------------------------------------------------+

對於第一條查詢語句,t1是驅動表,其有10000條記錄,內循環也就有10000次,這還得了?
對於第二條查詢語句,t2是驅動表,其有100條記錄,內循環100次,感覺不錯,我喜歡!
這些SQL語句的執行時間也說明了,當內連接時,務必用小表驅動大表。

最佳實踐:直接讓MySQL去判斷

但是,表的記錄數是會變化的,有沒有一勞永逸的寫法?當然有啦,MySQL自帶的Optimizer會優化內連接,優化策略就是上面講的小表驅動大表。所以,以后寫內連接不要糾結誰內連接誰了,直接讓MySQL去判斷吧。

    EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON t1.type=t2.type;
    EXPLAIN SELECT * FROM t2 INNER JOIN t1 ON t1.type=t2.type;
    EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.type=t2.type;
    EXPLAIN SELECT * FROM t2 JOIN t1 ON t1.type=t2.type;
    EXPLAIN SELECT * FROM t1,t2 WHERE t1.type=t2.type;
    EXPLAIN SELECT * FROM t2,t1 WHERE t1.type=t2.type;
    +----+-------+------+------+--------+----------------------------------------------------+
    | id | table | type | key  | rows   | Extra                                              |
    +----+-------+------+------+--------+----------------------------------------------------+
    |  1 | t2    | ALL  |  NULL|    100 | NULL                                               |
    |  1 | t1    | ALL  | NULL | 110428 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------+------+------+--------+----------------------------------------------------+

上面6條內連接SQL,MySQL的Optimizer都會進行優化。


免責聲明!

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



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