檢視合併(View Merging)
在使用檢視或巢狀檢視的查詢語句中,oracle 為了取得最優的執行計劃會將這些檢視進行合併,將檢視中的表與外部查詢的表進行連線。
- --示例:
- SQL> select e.first_name, e.last_name, dept_locs_v.street_address, dept_locs_v.postal_code
- 2 from employees e,
- 3 (select d.department_id, d.department_name, l.street_address, l.postal_code
- 4 from departments d, locations l
- 5 where d.location_id = l.location_id) dept_locs_v
- 6 where dept_locs_v.department_id = e.department_id
- 7 and e.last_name = 'Smith';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 994428606
- ---------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ---------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 56 | 4 (0)| 00:00:01 |
- | 1 | NESTED LOOPS | | 1 | 56 | 4 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 1 | 25 | 3 (0)| 00:00:01 |
- | 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 18 | 2 (0)| 00:00:01 |
- |* 4 | INDEX RANGE SCAN | EMP_NAME_IX | 1 | | 1 (0)| 00:00:01 |
- | 5 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 1 | 7 | 1 (0)| 00:00:01 |
- |* 6 | INDEX UNIQUE SCAN | DEPT_ID_PK | 1 | | 0 (0)| 00:00:01 |
- | 7 | TABLE ACCESS BY INDEX ROWID | LOCATIONS | 1 | 31 | 1 (0)| 00:00:01 |
- |* 8 | INDEX UNIQUE SCAN | LOC_ID_PK | 1 | | 0 (0)| 00:00:01 |
- ---------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - access("E"."LAST_NAME"='Smith')
- 6 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID")
- 8 - access("D"."LOCATION_ID"="L"."LOCATION_ID")
- --使用no_merge禁止檢視合併
- SQL> select /*+ no_merge(dept_locs_v)*/e.first_name, e.last_name, dept_locs_v.street_address, dept_locs_v.postal_code
- 2 from employees e,
- 3 (select d.department_id, d.department_name, l.street_address, l.postal_code
- 4 from departments d, locations l
- 5 where d.location_id = l.location_id) dept_locs_v
- 6 where dept_locs_v.department_id = e.department_id
- 7 and e.last_name = 'Smith';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 842533999
- --------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 61 | 7 (15)| 00:00:01 |
- |* 1 | HASH JOIN | | 1 | 61 | 7 (15)| 00:00:01 |
- | 2 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 18 | 2 (0)| 00:00:01 |
- |* 3 | INDEX RANGE SCAN | EMP_NAME_IX | 1 | | 1 (0)| 00:00:01 |
- | 4 | VIEW | | 27 | 1161 | 4 (0)| 00:00:01 |
- | 5 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 1 | 7 | 1 (0)| 00:00:01 |
- | 6 | NESTED LOOPS | | 27 | 1026 | 4 (0)| 00:00:01 |
- | 7 | TABLE ACCESS FULL | LOCATIONS | 23 | 713 | 3 (0)| 00:00:01 |
- |* 8 | INDEX RANGE SCAN | DEPT_LOCATION_IX | 4 | | 0 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("DEPT_LOCS_V"."DEPARTMENT_ID"="E"."DEPARTMENT_ID")
- 3 - access("E"."LAST_NAME"='Smith')
- 8 - access("D"."LOCATION_ID"="L"."LOCATION_ID")
可以使用hint來引導最佳化器,MERGE(v),合併檢視。NO_MERGE(v),如果在使用該檢視的父查詢中使用該提示,禁止該檢視被合併。
並不是任何使用檢視的查詢語句都會進行檢視合併,在檢視中出現以下操作時不能進行檢視合併:
Set operators(union,union all,intersact,minus)
Aggregation(avg,count,max,min,sum)
Rownum
Connect by
Group by(隱藏引數_complex_view_merging為true時,可能合併)
Distinct(隱藏引數_complex_view_merging為true時,可能合併)
- SQL> --使用rownum, 沒有合併
- SQL> select e.first_name, e.last_name, dept_locs_v.street_address, dept_locs_v.postal_code
- 2 from employees e,
- 3 (select rownum ,d.department_id, d.department_name, l.street_address, l.postal_code
- 4 from departments d, locations l
- 5 where d.location_id = l.location_id order by 2) dept_locs_v
- 6 where dept_locs_v.department_id = e.department_id
- 7 and e.last_name = 'Smith';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2276247677
- -----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 52 | 6 (17)| 00:00:01 |
- |* 1 | HASH JOIN | | 1 | 52 | 6 (17)| 00:00:01 |
- | 2 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 18 | 2 (0)| 00:00:01 |
- |* 3 | INDEX RANGE SCAN | EMP_NAME_IX | 1 | | 1 (0)| 00:00:01 |
- | 4 | VIEW | | 27 | 918 | 3 (0)| 00:00:01 |
- | 5 | COUNT | | | | | |
- | 6 | NESTED LOOPS | | 27 | 1350 | 3 (0)| 00:00:01 |
- | 7 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 513 | 2 (0)| 00:00:01 |
- | 8 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
- | 9 | TABLE ACCESS BY INDEX ROWID| LOCATIONS | 1 | 31 | 1 (0)| 00:00:01 |
- |* 10 | INDEX UNIQUE SCAN | LOC_ID_PK | 1 | | 0 (0)| 00:00:01 |
- -----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("DEPT_LOCS_V"."DEPARTMENT_ID"="E"."DEPARTMENT_ID")
- 3 - access("E"."LAST_NAME"='Smith')
- 10 - access("D"."LOCATION_ID"="L"."LOCATION_ID")
還有,當檢視在外連線的右側時,有些不能合併,有些能合併。
當檢視在外連線的左側,並且該檢視與外部查詢的同一表進行多於一次的外連線時,不能合併。這源於外連線的限制,外部查詢的每一個表最多隻能與檢視中的表進行一次連線。
- --當檢視在外連線的右側時,不能合併。
- SQL> select e1.first_name||' '||e1.last_name emp_name, dept_managers_v.manager_name,
- 2 dept_managers_v.department_name
- 3 from employees e1,
- 4 (select e2.manager_id, e2.first_name||' '||e2.last_name as manager_name,
- 5 d.department_id, d.department_name
- 6 from departments d, employees e2
- 7 where d.manager_id = e2.employee_id) dept_managers_v
- 8 where dept_managers_v.department_id(+) = e1.department_id;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3319085545
- ------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 107 | 7811 | 9 (12)| 00:00:01 |
- |* 1 | HASH JOIN OUTER | | 107 | 7811 | 9 (12)| 00:00:01 |
- | 2 | TABLE ACCESS FULL | EMPLOYEES | 107 | 1926 | 3 (0)| 00:00:01 |
- | 3 | VIEW | | 11 | 605 | 5 (0)| 00:00:01 |
- | 4 | NESTED LOOPS | | 11 | 418 | 5 (0)| 00:00:01 |
- |* 5 | TABLE ACCESS FULL | DEPARTMENTS | 11 | 209 | 3 (0)| 00:00:01 |
- | 6 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 19 | 1 (0)| 00:00:01 |
- |* 7 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
- ------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("DEPT_MANAGERS_V"."DEPARTMENT_ID"(+)="E1"."DEPARTMENT_ID")
- 5 - filter("D"."MANAGER_ID" IS NOT NULL)
- 7 - access("D"."MANAGER_ID"="E2"."EMPLOYEE_ID")
- --當檢視在外連線的左側,並且該檢視與外部查詢的同一表進行一次外連線時,能夠合併。
- SQL> select e1.first_name||' '||e1.last_name emp_name, dept_managers_v.manager_name,
- 2 dept_managers_v.department_name
- 3 from employees e1,
- 4 (select e2.manager_id, e2.first_name||' '||e2.last_name as manager_name,
- 5 d.department_id, d.department_name
- 6 from departments d, employees e2
- 7 where d.manager_id = e2.employee_id) dept_managers_v
- 8 where dept_managers_v.department_id = e1.department_id(+);
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 508024882
- -----------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 106 | 5936 | 8 (13)| 00:00:01 |
- | 1 | NESTED LOOPS | | 106 | 5936 | 8 (13)| 00:00:01 |
- | 2 | MERGE JOIN OUTER | | 106 | 3922 | 6 (17)| 00:00:01 |
- |* 3 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 11 | 209 | 2 (0)| 00:00:01 |
- | 4 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
- |* 5 | SORT JOIN | | 107 | 1926 | 4 (25)| 00:00:01 |
- | 6 | TABLE ACCESS FULL | EMPLOYEES | 107 | 1926 | 3 (0)| 00:00:01 |
- | 7 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 1 | 19 | 1 (0)| 00:00:01 |
- |* 8 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
- -----------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("D"."MANAGER_ID" IS NOT NULL)
- 5 - access("D"."DEPARTMENT_ID"="E1"."DEPARTMENT_ID"(+))
- filter("D"."DEPARTMENT_ID"="E1"."DEPARTMENT_ID"(+))
- 8 - access("D"."MANAGER_ID"="E2"."EMPLOYEE_ID")
- --當檢視在外連線的左側,並且該檢視與外部查詢的同一表進行多於一次的外連線時,不能合併。
- SQL> select e1.first_name||' '||e1.last_name emp_name, dept_managers_v.manager_name,
- 2 dept_managers_v.department_name
- 3 from employees e1,
- 4 (select e2.manager_id, e2.first_name||' '||e2.last_name as manager_name,
- 5 d.department_id, d.department_name
- 6 from departments d, employees e2
- 7 where d.manager_id = e2.employee_id) dept_managers_v
- 8 where dept_managers_v.department_id = e1.department_id(+)
- 9 and dept_managers_v.manager_id = e1.manager_id(+);
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 1655263574
- ------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 11 | 990 | 9 (12)| 00:00:01 |
- |* 1 | HASH JOIN OUTER | | 11 | 990 | 9 (12)| 00:00:01 |
- | 2 | VIEW | | 11 | 748 | 5 (0)| 00:00:01 |
- | 3 | NESTED LOOPS | | 11 | 462 | 5 (0)| 00:00:01 |
- |* 4 | TABLE ACCESS FULL | DEPARTMENTS | 11 | 209 | 3 (0)| 00:00:01 |
- | 5 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 23 | 1 (0)| 00:00:01 |
- |* 6 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
- | 7 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2354 | 3 (0)| 00:00:01 |
- ------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("DEPT_MANAGERS_V"."DEPARTMENT_ID"="E1"."DEPARTMENT_ID"(+) AND
- "DEPT_MANAGERS_V"."MANAGER_ID"="E1"."MANAGER_ID"(+))
- 4 - filter("D"."MANAGER_ID" IS NOT NULL)
- 6 - access("D"."MANAGER_ID"="E2"."EMPLOYEE_ID")
複雜檢視或巢狀檢視(包含有group by 或 distinct)的檢視合併由_complex_view_merging隱藏引數控制,當為true時,最佳化器評估可能應用檢視合併,當為false時,即使使用merge hint也不能應用檢視合併。以group by 為例:
當_complex_view_merging設定為true時,以下sql語句
select d.loc,v.avg_sal
from dept d,( select deptno,avg(sal) avg_sal,min(sal) min_sal,max(sal) max_sal
from emp group by deptno) v
where d.deptno=v.deptno and d.loc='CHICAGO';
可能會由查詢轉換器經檢視合併將其轉換為以下sql執行
select d.loc,avg(e.sal) avg_sal
from dept d,emp e
where d.deptno=e.deptno and d.loc='CHICAGO'
group by d.rowid,d.loc;
- SQL> conn / as sysdba
- 已連線。
- SQL> @hidParam.sql
- 輸入 parname 的值: _complex_view_merging
- 原值 3: WHERE x.indx = y.indx AND ksppinm = '&parName'
- 新值 3: WHERE x.indx = y.indx AND ksppinm = '_complex_view_merging'
- KSPPINM KSPPSTVL KSPPDESC
- --------------- ---------- --------------------------------------------------
- _complex_view_m TRUE enable complex view merging
- erging
- SQL> conn scott/tiger
- 已連線。
- SQL> select d.loc,v.avg_sal
- 2 from dept d,( select deptno,avg(sal) avg_sal,min(sal) min_sal,max(sal) max_sal
- 3 from emp group by deptno) v
- 4 where d.deptno=v.deptno and d.loc='CHICAGO';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2941989041
- ----------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 37 | 7 (43)| 00:00:01 |
- | 1 | NESTED LOOPS | | 1 | 37 | 7 (43)| 00:00:01 |
- | 2 | VIEW | | 3 | 78 | 6 (50)| 00:00:01 |
- | 3 | HASH GROUP BY | | 3 | 21 | 6 (50)| 00:00:01 |
- | 4 | TABLE ACCESS FULL | EMP | 10000 | 70000 | 4 (25)| 00:00:01 |
- |* 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 1 (0)| 00:00:01 |
- |* 6 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
- ----------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 5 - filter("D"."LOC"='CHICAGO')
- 6 - access("D"."DEPTNO"="V"."DEPTNO")
- --手動改變統計資訊
- SQL> exec dbms_stats.set_table_stats(user,'EMP',numrows=>100000);
- PL/SQL 過程已成功完成。
- --至此,應用了檢視合併
- SQL> select d.loc,v.avg_sal
- 2 from dept d,( select deptno,avg(sal) avg_sal,min(sal) min_sal,max(sal) max_sal
- 3 from emp group by deptno) v
- 4 where d.deptno=v.deptno and d.loc='CHICAGO';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2006461124
- ----------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 3 | 81 | 18 (67)| 00:00:01 |
- | 1 | HASH GROUP BY | | 3 | 81 | 18 (67)| 00:00:01 |
- |* 2 | HASH JOIN | | 33333 | 878K| 13 (54)| 00:00:01 |
- |* 3 | TABLE ACCESS FULL| DEPT | 1 | 20 | 3 (0)| 00:00:01 |
- | 4 | TABLE ACCESS FULL| EMP | 100K| 683K| 8 (63)| 00:00:01 |
- ----------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 2 - access("D"."DEPTNO"="DEPTNO")
- 3 - filter("D"."LOC"='CHICAGO')
- --將_complex_view_merging隱藏引數設定為false之後,即使使用merge引導最佳化器合併檢視也是枉然。
- SQL> alter session set "_complex_view_merging"=false;
- 會話已更改。
- SQL> select d.loc,v.avg_sal
- 2 from dept d,( select deptno,avg(sal) avg_sal,min(sal) min_sal,max(sal) max_sal
- 3 from emp group by deptno) v
- 4 where d.deptno=v.deptno and d.loc='CHICAGO';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2941989041
- ----------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 37 | 23 (83)| 00:00:01 |
- | 1 | NESTED LOOPS | | 1 | 37 | 23 (83)| 00:00:01 |
- | 2 | VIEW | | 3 | 78 | 22 (87)| 00:00:01 |
- | 3 | HASH GROUP BY | | 3 | 21 | 22 (87)| 00:00:01 |
- | 4 | TABLE ACCESS FULL | EMP | 100K| 683K| 8 (63)| 00:00:01 |
- |* 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 1 (0)| 00:00:01 |
- |* 6 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
- ----------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 5 - filter("D"."LOC"='CHICAGO')
- 6 - access("D"."DEPTNO"="V"."DEPTNO")
- SQL> select /*+ merge(v)*/ d.loc,v.avg_sal
- 2 from dept d,( select deptno,avg(sal) avg_sal,min(sal) min_sal,max(sal) max_sal
- 3 from emp group by deptno) v
- 4 where d.deptno=v.deptno and d.loc='CHICAGO';
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2941989041
- ----------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 37 | 23 (83)| 00:00:01 |
- | 1 | NESTED LOOPS | | 1 | 37 | 23 (83)| 00:00:01 |
- | 2 | VIEW | | 3 | 78 | 22 (87)| 00:00:01 |
- | 3 | HASH GROUP BY | | 3 | 21 | 22 (87)| 00:00:01 |
- | 4 | TABLE ACCESS FULL | EMP | 100K| 683K| 8 (63)| 00:00:01 |
- |* 5 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 11 | 1 (0)| 00:00:01 |
- |* 6 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
- ----------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 5 - filter("D"."LOC"='CHICAGO')
- 6 - access("D"."DEPTNO"="V"."DEPTNO")
sql語句如果不能進行檢視合併,這個時候oracle查詢轉換器同樣會對該sql進行一種轉換,將外部查詢的謂詞推入(Predicate Pushing)到檢視中基表,從而能夠使用索引訪問,進行這種轉換也是為了獲得最優的執行計劃。需要注意的一點是,謂詞推入的前提是該sql中的檢視沒有進行檢視合併。
同樣以巢狀檢視為例:
- SQL> create index ind_emp_deptno on emp(deptno);
- 索引已建立。
- SQL> set autot traceonly explain
- SQL> select d.loc,v.avg_sal
- 2 from dept d,( select e.deptno,avg(e.sal) avg_sal,min(e.sal) min_sal,max(e.sal) max_sal
- 3 from emp e group by e.deptno) v
- 4 where d.deptno=v.deptno and v.deptno=20;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3947471307
- ------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 27 | 2 (0)| 00:00:01 |
- | 1 | HASH GROUP BY | | 1 | 27 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 5 | 135 | 2 (0)| 00:00:01 |
- | 3 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |
- |* 4 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
- | 5 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 35 | 1 (0)| 00:00:01 |
- |* 6 | INDEX RANGE SCAN | IND_EMP_DEPTNO | 5 | | 0 (0)| 00:00:01 |
- ------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 4 - access("D"."DEPTNO"=20)
- 6 - access("E"."DEPTNO"=20)
- SQL> select /*+ no_merge(v) */d.loc,v.avg_sal
- 2 from dept d,( select e.deptno,avg(e.sal) avg_sal,min(e.sal) min_sal,max(e.sal) max_sal
- 3 from emp e group by e.deptno) v
- 4 where d.deptno=v.deptno and v.deptno=20;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 87641604
- -------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- -------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 1 | 37 | 3 (0)| 00:00:01 |
- | 1 | NESTED LOOPS | | 1 | 37 | 3 (0)| 00:00:01 |
- | 2 | TABLE ACCESS BY INDEX ROWID | DEPT | 1 | 11 | 1 (0)| 00:00:01 |
- |* 3 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
- | 4 | VIEW | | 1 | 26 | 2 (0)| 00:00:01 |
- | 5 | SORT GROUP BY | | 1 | 7 | 2 (0)| 00:00:01 |
- | 6 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 35 | 2 (0)| 00:00:01 |
- |* 7 | INDEX RANGE SCAN | IND_EMP_DEPTNO | 5 | | 1 (0)| 00:00:01 |
- -------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - access("D"."DEPTNO"=20)
- 7 - access("E"."DEPTNO"=20) --這裡將謂詞v.deptno=20推入到了基表e(emp),從而能夠使用索引訪問。
還有一種轉換叫做join謂詞推入。
通常情況下是不能透過基於索引的巢狀迴圈連線來訪問檢視的,因為檢視(與表不同)上沒有索引,而join謂詞推入能夠基於索引的巢狀迴圈連線來訪問該檢視 , 但是這樣的話也並不總是最優的;因為這同樣遵循當驅動行源資料量比較大時,hash 連線 或 sort-merge 連線 可能會帶來更好的效率。
以下型別的檢視支援(當不能檢視合併時才有可能推入)這一轉換:
UNION ALL/UNION view
Outer-joined view
Anti-joined view
Semi-joined view
DISTINCT view
GROUP-BY view
- SQL> create index ind_emp_dept_no on emp(deptno);
- 索引已建立。
- SQL> set autot traceonly explain
- SQL> select /*+ no_merge(v) */ d.loc,v.ename
- 2 from dept d,( select * from emp) v
- 3 where d.deptno=v.deptno(+) ;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2615629228
- ----------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 14 | 434 | 7 (15)| 00:00:01 |
- |* 1 | HASH JOIN OUTER | | 14 | 434 | 7 (15)| 00:00:01 |
- | 2 | TABLE ACCESS FULL | DEPT | 4 | 44 | 3 (0)| 00:00:01 |
- | 3 | VIEW | | 14 | 280 | 3 (0)| 00:00:01 |
- | 4 | TABLE ACCESS FULL| EMP | 14 | 126 | 3 (0)| 00:00:01 |
- ----------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("D"."DEPTNO"="V"."DEPTNO"(+))
- --使用no_merge保證檢視不能合併,push_pred 使join謂詞推入
- SQL> select /*+ no_merge(v) push_pred (v) */ d.loc,v.ename
- 2 from dept d,( select * from emp) v
- 3 where d.deptno=v.deptno(+) ;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 114584144
- -------------------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- -------------------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 14 | 350 | 11 (0)| 00:00:01 |
- | 1 | NESTED LOOPS OUTER | | 14 | 350 | 11 (0)| 00:00:01 |
- | 2 | TABLE ACCESS FULL | DEPT | 4 | 56 | 3 (0)| 00:00:01 |
- | 3 | VIEW PUSHED PREDICATE | | 1 | 11 | 2 (0)| 00:00:01 |
- | 4 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 60 | 2 (0)| 00:00:01 |
- |* 5 | INDEX RANGE SCAN | IND_EMP_DEPT_NO | 5 | | 1 (0)| 00:00:01 |
- -------------------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 5 - access("EMP"."DEPTNO"="D"."DEPTNO") --join謂詞已推入到基表,並訪問基表的索引。
- SQL> select /*+ no_merge(v) no_push_pred (v) */ d.loc,v.ename
- 2 from dept d,( select * from emp) v
- 3 where d.deptno=v.deptno(+) ;
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2615629228
- ----------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ----------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 14 | 434 | 7 (15)| 00:00:01 |
- |* 1 | HASH JOIN OUTER | | 14 | 434 | 7 (15)| 00:00:01 |
- | 2 | TABLE ACCESS FULL | DEPT | 4 | 44 | 3 (0)| 00:00:01 |
- | 3 | VIEW | | 14 | 280 | 3 (0)| 00:00:01 |
- | 4 | TABLE ACCESS FULL| EMP | 14 | 126 | 3 (0)| 00:00:01 |
- ----------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("D"."DEPTNO"="V"."DEPTNO"(+))
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26845409/viewspace-1673709/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【SQL優化器查詢變換器】檢視合併(View Merging)SQL優化View
- MySQL View 檢視MySqlView
- Prevents Merging An Inline ViewinlineView
- SQL優化一則:取消檢視合併SQL優化
- materialized view (物化檢視)ZedView
- 【SQL】Oracle查詢轉換之檢視合併SQLOracle
- Oracle 查詢轉換-02 View MergingOracleView
- MySQL View(檢視)詳解MySqlView
- 檢視所有VIEW/TABLE in MSSQLViewSQL
- Oracle查詢轉換(一)簡單檢視合併Oracle
- Oracle查詢轉換(二)複雜檢視合併Oracle
- Oracle查詢轉換(三)外連線檢視合併Oracle
- 建立物化檢視MV ( Materialized View )ZedView
- ThinkPHP框架檢視詳細介紹View檢視–模板(九)PHP框架View
- 在列印視窗,列印檢視View的子檢視結構圖View
- Oracle 12CR2查詢轉換之檢視合併Oracle
- hive中的 lateral view(側檢視)HiveView
- android 動畫 ——檢視動畫(View Animation)Android動畫View
- View Transform(檢視變換)詳解ViewORM
- 轉:物化檢視(Materialized View)介紹ZedView
- Dataguard (Standby) 相關的檢視(View)View
- 合併與拆分資料模型(MSDM:Merging & Spliting Data Modeling)模型
- 視訊合併軟體有什麼,怎麼合併多個視訊
- 如何合併視訊?是否適合新手操作?
- laravel利用artisan建立view檢視檔案LaravelView
- oracle parallel並行及px檢視viewOracleParallel並行View
- 對資料庫檢視view的理解資料庫View
- Android 合併生成分享圖片(View截圖)AndroidView
- nancy Unable to find view engine that could render the view 無法找到檢視模板引擎NaNView
- Linux使用ffmpeg合併視訊Linux
- _complex_view_merging對執行計劃的影響View
- 小程式開發基礎-view檢視容器View
- MSSQL索引檢視(indexed view)之簡述及使用SQL索引IndexView
- oracle10g materialized view物化檢視示例OracleZedView
- ogg 同步 物化檢視建立限制 Materialized ViewZedView
- 結合載入檢視使用
- 使用sitemesh建立複合檢視
- 利用檢視 V$FIXED_VIEW_DEFINITION 可以檢視Oracle很多底層的東西ViewOracle