MySQL如何执行关联查询
MySQL如何執行關聯查詢
MySQL中關聯一次意義比較廣泛,并不僅僅是一個查詢需要到2個表匹配才叫關聯,而是任何一個查詢都是一次關聯,每一個查詢,片段(包括子查詢單表的查詢)都可能是關聯
當前 MySQL 關聯執行策略很簡單:MySQL 對任何關聯都執行嵌套循環關聯操作,即 MySQL 現在一個表中循環取出單條數據,然后再嵌套到下一個表中尋找匹配的行,依次下去,直到找到所有表中匹配的行為止。然后根據各個表匹配的行,返回查詢中需要的各個列。MySQL 會嘗試在最后一個關聯表中找到所有匹配的行,如果最后一個關聯表無法找到更多的行以后,MySQL 返回到上一次關聯表,看是否能夠找到更多匹配記錄,依次迭代執行
按照這樣的方式查找第一個表記錄,再嵌套查詢下一個關聯表,然 后回溯到上一個表,在MySQL中是通過嵌套循環的方式實現——正如 其名 嵌套循環關聯
mysql> select tbl1.col1,tbl2.col2 from tbl1 inner join tbl2 using(col3) where tbl1.col1 in(5,6);假設mysql按照查詢中的表順序進行關聯操作,我們則可以用下面的偽代碼表示mysql將如何完成這個查詢:
outer_iter = iterator_over tbl1 where col1 in(3,4) outer_row = outer_iter.nextwhile outer_rowinner_iter = iterator over tbl2 where col3=outer_row.col3inner_row = inner_iter.nextwhile inner_rowoutput[outer_row.col1,inner_row.col2]inner_row = inner_iter.nextendout_row = outer_iter.next end上面的執行計劃對于單表查詢和多表關聯查詢都適用,如果是一個單表查詢,那么只需要完成上面的外層的基本操作。對于外連接和上面的執行過程任然適用。例如我們將上面的查詢修改如下:
mysql> SELECT tbl1.col1 ,tbl2.col2 FROM tbl1 left outer join tbl2 using (col3)WHERE tbl1.col1 in (3,4)偽代碼
outer_iter = iterator over tbl1 where col1 in(3,4) outer row = outer_iter.next while outer_rowinner_iter = iterator over tbl2 where col3 = outer_row.col3inner_row = inner_iter.nextif inner row while inner_rowout_put [outer_row.col1,inner_row.col2]inner_row = inner_iter.nextendelse out_put[outer_row.col1,NULL] endouter_row = outer_iter.next end另一種可視化查詢執行計劃的方法是根據優化器執行的路徑繪制出 對應的“泳道圖”請從左至右,從上至下地看這幅圖。
從本質上說,MySQL對所有的類型的查詢都以同樣的方式運行。 例如,MySQL在FROM子句中遇到子查詢時,先執行子查詢并將其結果 放到一個臨時表中,然后將這個臨時表當作一個普通表對待(正如 其名“派生表”)。MySQL在執行UNION查詢時也使用類似的臨時表,在遇到右外連接的時候,MySQL將其改寫成等價的左外連接。簡而言之,當前版本的MySQL會將所有的查詢類型都轉換成類似的執行計劃
不過,不是所有的查詢都可以轉換成上面的形式。例如,全外連接 就無法通過嵌套循環和回溯的方式完成,這時當發現關聯表中沒有找到 任何匹配行的時候,則可能是因為關聯是恰好從一個沒有任何匹配的表 開始。這大概也是MySQL并不支持全外連接的原因。還有些場景,雖 然可以轉換成嵌套循環的方式,但是效率卻非常差
MySQL 生成查詢的一顆指令樹,然后通過存儲引擎執行完成這顆指令樹big返回結果,任何多表查詢都可以使用一棵樹表示
在計算機科學中,這被稱為一顆平衡樹。但是,這并不是MySQL 執行查詢的方式。正如我們前面章節介紹的,MySQL總是從一個表開 始一直嵌套循環、回溯完成所有表關聯。所以,MySQL的執行計劃總是一棵左測深度優先的樹
mysql> explain select u.id,c.id from sys_user u left join sys_area c on c.id = u.city_id where u.id > 3;+----+-------------+-------+------------+--------+---------------+---------+---------+--------------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+--------+---------------+---------+---------+--------------+------+----------+-------------+ | 1 | SIMPLE | u | NULL | range | PRIMARY | PRIMARY | 8 | NULL | 10 | 100.00 | Using where | | 1 | SIMPLE | c | NULL | eq_ref | PRIMARY | PRIMARY | 8 | hr.u.city_id | 1 | 100.00 | Using index | +----+-------------+-------+------------+--------+---------------+---------+---------+--------------+------+----------+-------------+ 2 rows in set (0.06 sec)可以看出,首先在 sys_user 表上進行范圍查詢,篩選出 u.id > 3 的數據,然后在進行"嵌套查詢"。
總結
以上是生活随笔為你收集整理的MySQL如何执行关联查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库的内连接、左连接和右连接
- 下一篇: 《MySQL数据库》关联查询