當前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.next
while outer_row
inner_iter = iterator over tbl2 where col3=outer_row.col3
inner_row = inner_iter.next
while inner_row
output[outer_row.col1,inner_row.col2]
inner_row = inner_iter.next
endout_row = outer_iter.next
end上面的執行計畫對於單錶查詢和多表關聯查詢都適用,如果是乙個單錶查詢,那麼只需要完成上面的外層的基本操作。對於外連線和上面的執行過程任然適用。例如我們將上面的查詢修改如下:
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_row
inner_iter = iterator over tbl2 where col3 = outer_row.col3
inner_row = inner_iter.next
if inner row -> 手動加粗
while inner_row
out_put [outer_row.col1,inner_row.col2]
inner_row = inner_iter.next
endelse -> 手動加粗
out_put[outer_row.col1,null] -> 手動加粗
endouter_row = outer_iter.next
end從上面兩個例子也可以看出,對於主表來說,是先進行主表的where條件篩選,再進行表聯接,而不是先進行整表聯接再進行where條件的篩選。
舉個例子:
資料表結構:
mysql> create table a(
-> id int unsigned not null primary key
mysql> create table b like a;
表中資料:
mysql> select * from a;
| id |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
5 rows in set (0.00 sec)
mysql> select * from b;
| id |
| 4 |
| 5 |
| 6 |
| 7 |
4 rows in set (0.00 sec)
explain查詢:
mysql> explain select a.id as aid,b.id as bid from a left join b using(id) where a.id>3;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
| 1 | ****** | a | range | primary | primary | 4 | null | 3 | using where; using index |
| 1 | ****** | b | eq_ref | primary | primary | 4 | com.a.id | 1 | using index |
2 rows in set (0.00 sec)
可以看出,首先在a表上進行範圍查詢,篩選出a.id>3的資料,然後在進行"巢狀查詢"。
注意,on後面的篩選條件主要是針對的是關聯表,而對於主表篩選並不適用,比如:
mysql> select a.id as aid,b.id as bid from a left join b on a.id=b.id and a.id>3;
| aid | bid |
| 1 | null |
| 2 | null |
| 3 | null |
| 4 | 4 |
| 5 | 5 |
5 rows in set (0.00 sec)
mysql> explain select a.id as aid,b.id as bid from a left join b on a.id=b.id and a.id>3;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | extra |
| 1 | ****** | a | index | null | primary | 4 | null | 5 | using index |
| 1 | ****** | b | eq_ref | primary | primary | 4 | com.a.id | 1 | using index |
2 rows in set (0.00 sec)
我們發現a表的id<=3的資料並未被篩選走,explain的結果是a表進行了index型別的查詢,即主鍵索引的全部掃瞄。
如果在on的篩選條件是針對b表的呢,情況會怎麼樣?
下面的例子資料表結構和資料變了,我們只關注查詢的結果區別:
mysql> select * from a left join b on a.data=b.data and b.id<=20;
| id | data | id | data |
| 1 | 1 | null | null |
| 2 | 2 | null | null |
| 3 | 3 | null | null |
| 4 | 4 | 1 | 4 |
| 4 | 4 | 6 | 4 |
| 4 | 4 | 11 | 4 |
| 4 | 4 | 16 | 4 |
| 5 | 5 | 2 | 5 |
| 5 | 5 | 7 | 5 |
| 5 | 5 | 12 | 5 |
| 5 | 5 | 17 | 5 |
11 rows in set (0.00 sec)
mysql> select * from a left join b on a.data=b.data where b.id<=20;
| id | data | id | data |
| 4 | 4 | 1 | 4 |
| 5 | 5 | 2 | 5 |
| 4 | 4 | 6 | 4 |
| 5 | 5 | 7 | 5 |
| 4 | 4 | 11 | 4 |
| 5 | 5 | 12 | 5 |
| 4 | 4 | 16 | 4 |
| 5 | 5 | 17 | 5 |
8 rows in set (0.00 sec)
由此,我們可以根據偽碼來分析兩者的區別:
outer_iter = iterator over a
outer row = outer_iter.next
while outer_row
inner_iter = iterator over b where data = outer_row.date where id<=20
inner_row = inner_iter.next
if inner row
while inner_row
out_put [outer_row,inner_row]
inner_row = inner_iter.next
endelse
out_put[outer_row,null]
endouter_row = outer_iter.next
endouter_iter = iterator over a
outer row = outer_iter.next
while outer_row
inner_iter = iterator over b where data = outer_row.date ->手動加粗
inner_row = inner_iter.next
if inner row
while inner_row
out_put [outer_row,inner_row]
inner_row = inner_iter.next
endelse
out_put[outer_row,null]
endouter_row = outer_iter.next
endleft join的結果集中 where b.id<=20 ->手動加粗
mysql如何關聯 MySQL如何執行關聯查詢
mysql中 關聯 join 一詞包含的意義比一般意義上理解的要更廣泛。總的來說,mysql認為任何乙個查詢都是一次 關聯 並不僅僅是乙個查詢需要到兩個表的匹配才叫關聯,索引在mysql中,每乙個查詢,每乙個片段 包括子查詢,設定基於表單的select 都可能是關聯。所以,理解mysql如何執行關聯...
mysql 關聯刪除 mysql如何刪除關聯表
mysql資料庫中,表與表之間進行關聯之後,就不可隨意的進行刪除操作,否則會影響所有關聯表之間的結構,那麼如何安全的刪除關聯表呢,讓我們來了解一下。mysql使用drop命令刪除關聯表,方法為 1.刪除表的外來鍵約束 外來鍵是乙個特殊字段,其將某乙個表與其父表建立關聯關係。在建立表的時候,外來鍵約束...
mysql關聯子查詢 MySQL 關聯子查詢
mysql 關聯子查詢 關聯子查詢是指乙個包含對錶的引用的子查詢,該錶也顯示在外部查詢中。通俗一點來講,就是子查詢引用到了主查詢的資料資料。以乙個實際的例子來理解關聯子查詢 article 文章表 aidtitlecontentuid 文章1文章1正文內容.文章2文章2正文內容.文章3文章3正文內容...