首頁 > 資料庫 > mysql教程 > Mysql表連接的執行流程是什麼

Mysql表連接的執行流程是什麼

PHPz
發布: 2023-06-01 17:26:23
轉載
1442 人瀏覽過

    1. 前言

    對於連接操作,驅動表和被驅動表的關聯條件我們放在on後面,如果額外增加對驅動表和被驅動表的篩選條件,放到on或where後面都不會報錯,但是得到的結果集卻是不一樣的? ? ?

    1.1 mysql連接的原理

    眾所周知,mysql是基於嵌套循環連接(Nested-Loop Join,暫時不考慮優化演算法)演算法來進行表之間的連接操作的,大致流程如下:

    • 選取驅動表,使用與驅動程式表相關的篩選條件執行對驅動程式表的單表查詢;

    • 對於查詢到的驅動表中的每一個紀錄,分別到被驅動表中尋找匹配的紀錄。

    偽代碼如下:

    for each row in t1 {      // 遍历满足对t1单表查询结果集中的每一条纪录
        for each row in t2 {  // 对于某条t1纪录,遍历满足对t2单表查询结果集中的每一条纪录
            if row satisfies join conditions, send to client
        }
    }
    登入後複製

    #1.2 show warnings指令

    我們寫的sql語句,在經過最佳化器最佳化之後才會交給執行器執行,而show warnings指令則可以幫助我們取得優化器最佳化後的sql。

    2. 準備工作

    表格結構如下:

    CREATE TABLE `student` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `stu_code` varchar(20) NOT NULL DEFAULT '',
      `stu_name` varchar(30) NOT NULL DEFAULT '',
      `stu_sex` varchar(10) NOT NULL DEFAULT '',
      `stu_age` int(10) NOT NULL DEFAULT '0',
      `stu_dept` varchar(30) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`) USING BTREE,
      UNIQUE KEY `uq_stu_code` (`stu_code`)
    ) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4
    
    CREATE TABLE `course` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `cou_code` varchar(20) NOT NULL DEFAULT '',
      `cou_name` varchar(50) NOT NULL DEFAULT '',
      `cou_score` int(10) NOT NULL DEFAULT '0',
      `stu_code` varchar(20) NOT NULL DEFAULT '',
      PRIMARY KEY (`id`) USING BTREE,
      KEY `idx_stu_code_cou_code` (`stu_code`,`cou_code`)
    ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4
    登入後複製

    表格資料如下: 

    Mysql表連接的執行流程是什麼

    3. inner join內連接on、where的差異

    #sql如下:

    select * from student
    inner join course on student.stu_code = course.stu_code
    and student.stu_code >= 3 and course.cou_score >= 80;
    登入後複製

    執行explain sql指令: 

    Mysql表連接的執行流程是什麼

    執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    分析:從show warnings分析來看,對於inner join連接,經過最佳化器最佳化後,on連接條件會轉換為where!也就是說內連接中的where和on是等價的

    4. left join左連接on、where的區別

    4.1 where驅動表過濾條件

    sql如下:

    select * from student
    left join course on student.stu_code = course.stu_code
    where student.stu_code >= 3;
    登入後複製

    執行explain sql指令: 

    Mysql表連接的執行流程是什麼

    #執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    ##執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    #結果集: 

    #分析:從explain分析看出,student當作驅動表,把student.stu_code >= 3作為過濾條件進行全表掃描,然後把查詢到的每條紀錄的student.stu_code(也就是on條件裡面的)分別作為過濾條件讓被驅動表course做單表查詢。

    4.2 on驅動程式表篩選條件

    sql如下:

    select * from student
    left join course on student.stu_code = course.stu_code 
    and student.stu_code >= 3;
    登入後複製
    Mysql表連接的執行流程是什麼

    執行explain sql指令: 

    Mysql表連接的執行流程是什麼

    #執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    #結果集: 

    #從結果集來看,student.stu_code >= 3並未生效,為什麼?

    分析:

    從explain分析看出,student作為驅動表,做全表掃描,然後把查詢到的每筆記錄的student.stu_code和student.stu_code >= 3 (也就是on條件裡面的)分別做為過濾條件讓被驅動表做單表查詢;

    此時student.stu_code >= 3對驅動表是不過濾的,僅在連接被驅動表時生效,查詢不到符合紀錄而回傳NULL!

    4.3 on被驅動程式表篩選條件

    sql如下:

    select * from student
    left join course on student.stu_code = course.stu_code 
    and course.cou_score >= 80;
    登入後複製
    Mysql表連接的執行流程是什麼執行explain sql指令: 

    Mysql表連接的執行流程是什麼

    #執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    結果集: ##### ###########

    分析:從explain分析看出,student作為驅動表,做全表掃描,然後把查詢到的每筆記錄的student.stu_code和course.cou_score >= 80(也就是on條件裡面的)分別做為過濾條件讓被驅動表做單表查詢;

    4.4 where被驅動表過濾條件

    sql如下: 

    Mysql表連接的執行流程是什麼

    執行explain sql指令: 

    Mysql表連接的執行流程是什麼

    執行show warnings指令: 

    Mysql表連接的執行流程是什麼

    #結果集: 

    Mysql表連接的執行流程是什麼

    #從show warnings分析來看? left join連線變成了inner join連線?

    分析:從show warnings分析看出,如果被驅動表有過濾條件在where,那麼left join會被失效,被優化成inner join連接。所以被驅動表的篩選條件應該放在on而不是where

    以上是Mysql表連接的執行流程是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    相關標籤:
    來源:yisu.com
    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
    熱門教學
    更多>
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板