--Join Predicate Pushdowncreate table emp1 as select * from scott.emp create table emp2 as select * from scott.emp create index idx_emp1 on emp1(empno);create index idx_emp2 on emp2(empno);create or replace view emp_view as select emp1.empno as empno1 from emp1create or replace view emp_view_union as select emp1.empno as empno1 from emp1 union allselect emp2.empno as empno2 from emp2select /*+ no_merge(emp_view) */emp.empno from emp,emp_viewwhere emp.empno = emp_view.empno1(+) and emp.ename = 'FORD' Plan Hash Value : 101695337 ------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 22 | 3 | 00:00:01 || 1 | NESTED LOOPS OUTER | | 1 | 22 | 3 | 00:00:01 || * 2 | TABLE ACCESS FULL | EMP | 1 | 20 | 2 | 00:00:01 || 3 | VIEW PUSHED PREDICATE | EMP_VIEW | 1 | 2 | 1 | 00:00:01 || * 4 | INDEX RANGE SCAN | IDX_EMP1 | 1 | 13 | 1 | 00:00:01 |------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - filter("EMP"."ENAME"='FORD')* 4 - access("EMP1"."EMPNO"="EMP"."EMPNO") --谓词推入select /*+ no_merge(emp_view) no_push_pred(emp_view) */ --禁止谓词推入,视图合并emp.empno from emp,emp_viewwhere emp.empno = emp_view.empno1(+) and emp.ename = 'FORD' Plan Hash Value : 1524044994 --------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 33 | 3 | 00:00:01 || * 1 | HASH JOIN OUTER | | 1 | 33 | 3 | 00:00:01 || * 2 | TABLE ACCESS FULL | EMP | 1 | 20 | 2 | 00:00:01 || 3 | VIEW | EMP_VIEW | 15 | 195 | 1 | 00:00:01 || 4 | INDEX FULL SCAN | IDX_EMP1 | 15 | 195 | 1 | 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 1 - access("EMP"."EMPNO"="EMP_VIEW"."EMPNO1"(+))* 2 - filter("EMP"."ENAME"='FORD')--视图中含有union allselect emp.empno from emp,emp_view_unionwhere emp.empno = emp_view_union.empno1 and emp.ename = 'FORD'Plan Hash Value : 152695365 ------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 2 | 66 | 4 | 00:00:01 || 1 | NESTED LOOPS OUTER | | 2 | 66 | 4 | 00:00:01 || * 2 | TABLE ACCESS FULL | EMP | 1 | 20 | 2 | 00:00:01 || 3 | VIEW /*没有进行视图合并 *| |MP_VIEW_UNION | 1 | 13 | 2 | 00:00:01 || 4 | UNION ALL PUSHED PREDICATE | /* 谓词推入*/ | | | | || * 5 | INDEX RANGE SCAN | IDX_EMP1 | 1 | 13 | 1 | 00:00:01 || * 6 | INDEX RANGE SCAN | IDX_EMP2 | 1 | 13 | 1 | 00:00:01 |------------------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - filter("EMP"."ENAME"='FORD')* 5 - access("EMP1"."EMPNO"="EMP"."EMPNO")* 6 - access("EMP2"."EMPNO"="EMP"."EMPNO")Note------ dynamic sampling used for this statement--谓词推入条件;视图中含有union all,不能进行视图合并,视图基表的链接条件上已经有了索引*/--如果禁止谓词推入,那么视图可能走出全表或者索引全扫描select /*+ no_push_pred(emp_view_union) */emp.empno from emp,emp_view_unionwhere emp.empno = emp_view_union.empno1 and emp.ename = 'FORD' Plan Hash Value : 2461179762 --------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |--------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 2 | 66 | 4 | 00:00:01 || * 1 | HASH JOIN | | 2 | 66 | 4 | 00:00:01 || * 2 | TABLE ACCESS FULL | EMP | 1 | 20 | 2 | 00:00:01 || 3 | VIEW | EMP_VIEW_UNION | 30 | 390 | 2 | 00:00:01 || 4 | UNION-ALL | | | | | || 5 | INDEX FULL SCAN | IDX_EMP1 | 15 | 195 | 1 | 00:00:01 || 6 | INDEX FULL SCAN | IDX_EMP2 | 15 | 195 | 1 | 00:00:01 |--------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 1 - access("EMP"."EMPNO"="EMP_VIEW_UNION"."EMPNO1")* 2 - filter("EMP"."ENAME"='FORD')Note------ dynamic sampling used for this statement---CBO在做谓词推入的时候会考虑成本;如果谓词推入后成本大于之前的,那么不会进行谓词推入select /*+ cardinality(emp 1000000) */emp.empno from emp,emp_view_unionwhere emp.empno = emp_view_union.empno1 and emp.ename = 'FORD' Plan Hash Value : 1728342133 ------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 2000000 | 66000000 | 25 | 00:00:01 || 1 | MERGE JOIN | | 2000000 | 66000000 | 25 | 00:00:01 || * 2 | TABLE ACCESS BY INDEX ROWID | EMP | 1000000 | 20000000 | 10 | 00:00:01 || 3 | INDEX FULL SCAN | SYS_C0093796 | 15 | | 2 | 00:00:01 || * 4 | SORT JOIN | | 30 | 390 | 3 | 00:00:01 || 5 | VIEW | EMP_VIEW_UNION | 30 | 390 | 2 | 00:00:01 || 6 | UNION-ALL | | | | | || 7 | INDEX FULL SCAN | IDX_EMP1 | 15 | 195 | 1 | 00:00:01 || 8 | INDEX FULL SCAN | IDX_EMP2 | 15 | 195 | 1 | 00:00:01 |------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - filter("EMP"."ENAME"='FORD')* 4 - access("EMP"."EMPNO"="EMP_VIEW_UNION"."EMPNO1")* 4 - filter("EMP"."EMPNO"="EMP_VIEW_UNION"."EMPNO1")Note------ dynamic sampling used for this statement--如果此时强制谓词推入,按照oracle 成本估算大大增加select /*+ cardinality(emp 1000000) push_pred(emp_view_union) */emp.empno from emp,emp_view_unionwhere emp.empno = emp_view_union.empno1 and emp.ename = 'FORD' Plan Hash Value : 2223410919 ---------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |---------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1000000 | 33000000 | 2001778 | 06:40:22 || 1 | NESTED LOOPS | | 1000000 | 33000000 | 2001778 | 06:40:22 || * 2 | TABLE ACCESS FULL | EMP | 1000000 | 20000000 | 2 | 00:00:01 || 3 | VIEW | EMP_VIEW_UNION | 1 | 13 | 2 | 00:00:01 || 4 | UNION ALL PUSHED PREDICATE | | | | | || * 5 | INDEX RANGE SCAN | IDX_EMP1 | 1 | 13 | 1 | 00:00:01 || * 6 | INDEX RANGE SCAN | IDX_EMP2 | 1 | 13 | 1 | 00:00:01 |---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - filter("EMP"."ENAME"='FORD')* 5 - access("EMP1"."EMPNO"="EMP"."EMPNO")* 6 - access("EMP2"."EMPNO"="EMP"."EMPNO")Note------ dynamic sampling used for this statement---内联视图,也会进行谓词推入的select /*+ no_merge(emp_view_inline) */emp.empno from emp,(select emp1.empno as empno1 from emp1) emp_view_inlinewhere emp.empno = emp_view_inline.empno1(+) and emp.ename = 'FORD'Plan Hash Value : 3347874242 ------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 22 | 3 | 00:00:01 || 1 | NESTED LOOPS OUTER | | 1 | 22 | 3 | 00:00:01 || * 2 | TABLE ACCESS FULL | EMP | 1 | 20 | 2 | 00:00:01 || 3 | VIEW PUSHED PREDICATE | | 1 | 2 | 1 | 00:00:01 || * 4 | INDEX RANGE SCAN | IDX_EMP1 | 1 | 13 | 1 | 00:00:01 |------------------------------------------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - filter("EMP"."ENAME"='FORD')* 4 - access("EMP1"."EMPNO"="EMP"."EMPNO")Note------ dynamic sampling used for this statement/* 能否做谓词推入与目标视图是否能做视图合并,是否是内联视图没有关系但是与目标视图的类型,与外部查询之间的链接类型以及链接方法有关系 仅包含以下几种视图定义中含有union all,union, distinct,group by,和外部查询之间是外连接,反连接,半连接*/--以下就无法做谓词推入,即使加入HINTselect /*+ no_merge(emp_view) push_pred(emp_view) */emp.empno from emp,emp_viewwhere emp.empno = emp_view.empno1 and emp.ename = 'FORD'