一般的情况下外连接如下a right join b on a.id=b.id 那么b一定要作为驱动表,原因在于只有b作为驱动表才能得到完整的结果集,如果a作为驱动,那么返回的结果集
可能不完整,但是在特殊的情况的,可能将外连接转换为内连接
考虑如下的情况
b
id name
1 g1
1 g2
2 g3
2 g4
a
id name
2 gname2
使用如下语句:
select b.id,a.id from
a right join b on a.id=b.id
where a.id=2;
先不考虑where a.id=1;
做外连接返回的值应该为
b.id a.id
1 null
1 null
2 2
2 2
现在来考虑a.id =2 ;
那么如果这样过滤那么结果集合如下:
b.id a.id
2 2
2 2
这正是内连接的得到的结果集,也就是说只要a.id 限定为一定固定的非空的值,内连接出来的结构集就能
完全的满足谓词条件过滤后得到结果的全部中间结果集,那么数据库将会进行转换。MYSQL ORACLE都是如此
mysql:
mysql> explain select b.id,a.id from a right join b on a.id=b.id where a.id =2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)
a作为了驱动表
oracle:
SQL> select b.id from a right join b on a.id=b.id where a.id=2;
Execution Plan
----------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 5 (20)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 26 | 5 (20)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| B | 2 | 26 | 2 (0)| 00:00:01 |
可以看到本该出现的 HASH JOIN OUTER 没有出现。
但是如果将条件where a.id=2;改为where a.id is null;那么显然这种转换不合理,因为
内连接出来的结果集已经不能满足 a.id is null;的要求。
为什么要这样转换,我们知道在做连接的时候不管是NEST LOOP和HASN JOIN都应该把小表
作为驱动表,效率一般更高,那么外连接限定死了顺序可能大表做为驱动表,那么效率
显然更低,如果做了内连接的转换那么选择的顺序就更多,效率可能得到提高,当然
这和统计数据的精准度有很大的关系。
可能不完整,但是在特殊的情况的,可能将外连接转换为内连接
考虑如下的情况
b
id name
1 g1
1 g2
2 g3
2 g4
a
id name
2 gname2
使用如下语句:
select b.id,a.id from
a right join b on a.id=b.id
where a.id=2;
先不考虑where a.id=1;
做外连接返回的值应该为
b.id a.id
1 null
1 null
2 2
2 2
现在来考虑a.id =2 ;
那么如果这样过滤那么结果集合如下:
b.id a.id
2 2
2 2
这正是内连接的得到的结果集,也就是说只要a.id 限定为一定固定的非空的值,内连接出来的结构集就能
完全的满足谓词条件过滤后得到结果的全部中间结果集,那么数据库将会进行转换。MYSQL ORACLE都是如此
mysql:
mysql> explain select b.id,a.id from a right join b on a.id=b.id where a.id =2;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 2 | Using where |
| 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)
a作为了驱动表
oracle:
SQL> select b.id from a right join b on a.id=b.id where a.id=2;
Execution Plan
----------------------------------------------------------
Plan hash value: 652036164
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 5 (20)| 00:00:01 |
|* 1 | HASH JOIN | | 1 | 26 | 5 (20)| 00:00:01 |
|* 2 | TABLE ACCESS FULL| A | 1 | 13 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| B | 2 | 26 | 2 (0)| 00:00:01 |
可以看到本该出现的 HASH JOIN OUTER 没有出现。
但是如果将条件where a.id=2;改为where a.id is null;那么显然这种转换不合理,因为
内连接出来的结果集已经不能满足 a.id is null;的要求。
为什么要这样转换,我们知道在做连接的时候不管是NEST LOOP和HASN JOIN都应该把小表
作为驱动表,效率一般更高,那么外连接限定死了顺序可能大表做为驱动表,那么效率
显然更低,如果做了内连接的转换那么选择的顺序就更多,效率可能得到提高,当然
这和统计数据的精准度有很大的关系。