外連線轉換為內連線的情況
一般的情況下外連線如下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都應該把小表
作為驅動表,效率一般更高,那麼外連線限定死了順序可能大表做為驅動表,那麼效率
顯然更低,如果做了內連線的轉換那麼選擇的順序就更多,效率可能得到提高,當然
這和統計資料的精準度有很大的關係。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2123022/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 內連線、外連線
- SQL的四種連線:內連線 左外連線 右外連線 全連線SQL
- 【SQL】Oracle的內連線、左外連線、右外連線及全外連線SQLOracle
- 轉載:內連線與外連線的區別
- Oracle內連線、外連線、右外連線、全外連線小總結Oracle
- sql 內連線和外連線SQL
- 內連線、外連線總結
- 深入理解SQL的四種連線-左外連線、右外連線、內連線、全連線SQL
- 例項解析外連線 內連線 自連線 全連線
- MYSQL語法:左連線、右連線、內連線、全外連線MySql
- MySQL筆記3——內連線/外連線、多表連線MySql筆記
- 伺服器的連線情況?伺服器
- sql內連結,外連線SQL
- Oracle 表連線方式詳解(外連結、內連線、自連線)Oracle
- sql和hql中join語句區別,以及hibernate中內連線,迫切內連線,左外連線,迫切左外連線,右外連線的區別(合集)...SQL
- 行的儲存(塊內連線與塊外連線)
- SQL Server中內連線和外連線的區別SQLServer
- 資料庫外連線,自然連線,內連線,條件連線,等值連線關係及詳解資料庫
- 內連線、左連線、右連線
- 你真的會玩SQL嗎?內連線、外連線SQL
- oracle sql內連線_左(右)連線_全外連線_幾種寫法OracleSQL
- 監控oracle的連線(session)情況[Z]OracleSession
- 內聯,左外聯,右外聯,全連線,交叉連線 的區別
- 3.DQL資料查詢語言(內連線,外連線,自連線)
- Oracle左外連線、右外連線、完全外連線以及(+)號用法Oracle
- Oracle 左外連線、右外連線、全外連線小總結Oracle
- not exists改為外連線
- Mysql——內外連線,事物,索引MySql索引
- MYSQL學習筆記23: 多表查詢(自連線內連線+左右外連線)MySql筆記
- exists改為內連線
- 外連線與連線順序
- SQL SERVER 自連線、外連線SQLServer
- SQL 改寫系列十:半連線轉內連線SQL
- SQL改寫系列九:外連線轉內連線的常見場景與錯誤SQL
- 將not exists更改為外連線
- Oracle 內外連線 join 總結Oracle
- T-SQL學習中–內聯接,外連線,交叉連線SQL
- SQL改寫系列九:外連線轉內連線的常見場景與錯誤-2SQL