--Join Predicate Pushdown
create 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 emp1
create or replace view emp_view_union as
select emp1.empno as empno1 from emp1 union all
select emp2.empno as empno2 from emp2
select /*+ no_merge(emp_view) */
emp.empno
from emp, emp_view
where 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_view
where 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 all
select emp.empno
from emp, emp_view_union
where 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_union
where 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_union
where 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_union
where 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_inline
where 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,和外部查询之间是外连接,
反连接,半连接*/
--以下就无法做谓词推入,即使加入HINT
select /*+ no_merge(emp_view) push_pred(emp_view) */
emp.empno
from emp, emp_view
where emp.empno = emp_view.empno1
and emp.ename = ‘FORD‘