在Oracle数据库中,层级查询可以很方便地查询含义等级关系的数据,例如工资表与部门表之间的下属关系。
而在实际应用中,多数情况下这些关系数据分布在多个表中,需要跨表进行层级查询。
对于两种方式连接多表:隐式连接和显示连接。隐式连接指没有明确指定JOIN子句;
显示连接指明确使用JOIN关键字指定连接方式。
这两种连接方式在WHERE子句中的连接条件下推上具有区别:
对于隐式连接,Oracle会试图将WHERE子句中的连接条件下推到实际的连接操作中。
而对于显示连接,由于用户已经明确指定了连接逻辑,Oracle不会再修改用户定义的连接条件下推位置。
下推连接条件的影响很明显:
对于隐式连接,连接条件下推后可以利用索引更快地连接表,通常性能更优。
但是如果条件下推错误,可能导致结果错误。
所以,在实际开发中需要灵活选择:
比如下面的 sql ,隐式的多表关联查询(没有显示的写 join )。
SELECT s1.staff_id, s1.name, s1.manager_id FROM staff_table s1, staff_table_2 s2 WHERE s1.staff_id = s2.staff_id AND s1.staff_id > 1001 START WITH s1.staff_id = '1001' CONNECT BY PRIOR s1.staff_id = s1.manager_id;
Oracle 执行计划如下,可以看到 WHERE 子句中的 s1.staff_id = s2.staff_id 被下推到了连接节点,而 s1.staff_id > 1001 还是保留在原来的位置。
------------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | FILTER | |
|* 2 | CONNECT BY NO FILTERING WITH START-WITH| |
| 3 | NESTED LOOPS | |
| 4 | TABLE ACCESS FULL | STAFF_TABLE |
|* 5 | INDEX UNIQUE SCAN | SYS_C00109736 |
------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("S1"."STAFF_ID">1001)
2 - access("S1"."MANAGER_ID"=PRIOR "S1"."STAFF_ID")
filter("S1"."STAFF_ID"=1001)
5 - access("S1"."STAFF_ID"="S2"."STAFF_ID")
如果显示的指定了 join ,那么 where 条件中的连接条件就不能再进行下推,否则结果错误。
SELECT s1.staff_id, s1.name, s1.manager_id
FROM staff_table s1 join staff_table_2 s2
ON s1.manager_id = s2.manager_id
WHERE s1.staff_id = s2.staff_id AND s1.staff_id > 1001
START WITH s1.staff_id = '1001'
CONNECT BY PRIOR s1.staff_id = s1.manager_id;
------------------------------------------------------------------
| Id | Operation | Name |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | FILTER | |
|* 2 | CONNECT BY NO FILTERING WITH START-WITH| |
|* 3 | HASH JOIN | |
| 4 | TABLE ACCESS FULL | STAFF_TABLE |
| 5 | TABLE ACCESS FULL | STAFF_TABLE_2 |
------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("S1"."STAFF_ID"="S2"."STAFF_ID" AND "S1"."STAFF_ID">1001)
2 - access("S1"."MANAGER_ID"=PRIOR "S1"."STAFF_ID")
filter("S1"."STAFF_ID"=1001)
3 - access("S1"."MANAGER_ID"="S2"."MANAGER_ID")
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69982913/viewspace-3007059/ ,如需转载,请注明出处,否则将追究法律责任。