WITH Clause : Subquery Factoring
2014-02-27 17:37
639 查看
转自:http://www.oracle-base.com/articles/misc/with-clause.php#Top
MATERIALIZE Hint
PL/SQL Declaration Section
Related articles.
WITH Clause Enhancements in Oracle Database 12c Release 1 (12cR1)
is that repeated references to the subquery may be more efficient as the data is easily retrieved from the temporary table, rather than being requeried by each reference. You should assess the performance implications of the
This article shows how the
WITH clause.
Using the SCOTT schema, for each employee we want to know how many other people are in their department. Using an inline view we might do the following.
Using a
The difference seems rather insignificant here.
What if we also want to pull back each employees manager name and the number of people in the managers department? Using the inlineview it now looks like this.
Using the
So we don't need to redefine the same subquery multiple times. Instead we just use the query name defined in the
If the contents of the
Even when there is no repetition of SQL, the
In the previous example, the main body of the query is very simple, with the complexity hidden in the
Create a test table.
Check the trace file location.
Trace a statement using the
The following abbreviated output shows some points of interest in the resulting trace file. Notice the "CREATE GLOBAL TEMPORARY T" and "TABLE ACCESS FULL SYS_TEMP_0FD9D662B_2E34FB" lines. It certainly seems to be using a global temporary table.
Note. This is an undocumented feature. I've given you an example that uses a global temporary table, but perhaps there are other circumstances that don't.
here.
For more information see:
WITH Clause Enhancements in Oracle Database 12c Release 1 (12cR1)
subquery_factoring_clause
Hope this helps. Regards Tim...
Back to the Top.
WITH Clause : Subquery Factoring
Subquery FactoringMATERIALIZE Hint
PL/SQL Declaration Section
Related articles.
WITH Clause Enhancements in Oracle Database 12c Release 1 (12cR1)
Subquery Factoring
TheWITHclause, or subquery factoring clause, is part of the SQL-99 standard and was added into the Oracle SQL syntax in Oracle 9.2. The WITH clause may be processed as an inline view or resolved as a temporary table. The advantage of the latter
is that repeated references to the subquery may be more efficient as the data is easily retrieved from the temporary table, rather than being requeried by each reference. You should assess the performance implications of the
WITHclause on a case-by-case basis.
This article shows how the
WITHclause can be used to reduce repetition and simplify complex SQL statements. I'm not suggesting the following queries are the best way to retrieve the required information. They merely demonstrate the use of the
WITH clause.
Using the SCOTT schema, for each employee we want to know how many other people are in their department. Using an inline view we might do the following.
SELECT e.ename AS employee_name, dc.dept_count AS emp_dept_count FROM emp e, (SELECT deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) dc WHERE e.deptno = dc.deptno;
Using a
WITHclause this would look like the following.
WITH dept_count AS ( SELECT deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) SELECT e.ename AS employee_name, dc.dept_count AS emp_dept_count FROM emp e, dept_count dc WHERE e.deptno = dc.deptno;
The difference seems rather insignificant here.
What if we also want to pull back each employees manager name and the number of people in the managers department? Using the inlineview it now looks like this.
SELECT e.ename AS employee_name, dc1.dept_count AS emp_dept_count, m.ename AS manager_name, dc2.dept_count AS mgr_dept_count FROM emp e, (SELECT deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) dc1, emp m, (SELECT deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) dc2 WHERE e.deptno = dc1.deptno AND e.mgr = m.empno AND m.deptno = dc2.deptno;
Using the
WITHclause this would look like the following.
WITH dept_count AS ( SELECT deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) SELECT e.ename AS employee_name, dc1.dept_count AS emp_dept_count, m.ename AS manager_name, dc2.dept_count AS mgr_dept_count FROM emp e, dept_count dc1, emp m, dept_count dc2 WHERE e.deptno = dc1.deptno AND e.mgr = m.empno AND m.deptno = dc2.deptno;
So we don't need to redefine the same subquery multiple times. Instead we just use the query name defined in the
WITHclause, making the query much easier to read.
If the contents of the
WITHclause is sufficiently complex, Oracle may decide to resolve the result of the subquery into a global temporary table. This can make multiple references to the subquery more efficient. The
MATERIALIZEand
INLINEoptimizer hints can be used to influence the decision. The undocumented
MATERIALIZEhint tells the optimizer to resolve the subquery as a global temporary table, while the
INLINEhint tells it to process the query inline.
WITH dept_count AS ( SELECT /*+ MATERIALIZE */ deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) SELECT ... WITH dept_count AS ( SELECT /*+ INLINE */ deptno, COUNT(*) AS dept_count FROM emp GROUP BY deptno) SELECT ...
Even when there is no repetition of SQL, the
WITHclause can simplify complex queries, like the following example that lists those departments with above average wages.
WITH dept_costs AS ( SELECT dname, SUM(sal) dept_total FROM emp e, dept d WHERE e.deptno = d.deptno GROUP BY dname), avg_cost AS ( SELECT SUM(dept_total)/COUNT(*) avg FROM dept_costs) SELECT * FROM dept_costs WHERE dept_total > (SELECT avg FROM avg_cost) ORDER BY dname;
In the previous example, the main body of the query is very simple, with the complexity hidden in the
WITHclause.
MATERIALIZE Hint
The undocumentedMATERIALIZEhint was mentioned above, but there seems to be a little confusion over how it is implemented. We can see what is happening under the covers using SQL trace.
Create a test table.
CONN test/test CREATE TABLE t1 AS SELECT level AS id FROM dual CONNECT BY level <= 100;
Check the trace file location.
SELECT value FROM v$diag_info WHERE name = 'Default Trace File'; VALUE -------------------------------------------------------------------------------- /u01/app/oracle/diag/rdbms/cdb1/cdb1/trace/cdb1_ora_4278.trc SQL>
Trace a statement using the
MATERIALIZEhint.
EXEC DBMS_MONITOR.session_trace_enable; WITH query1 AS ( SELECT /*+ MATERIALIZE */ * FROM t1 ) SELECT * FROM query1; EXEC DBMS_MONITOR.session_trace_disable;
The following abbreviated output shows some points of interest in the resulting trace file. Notice the "CREATE GLOBAL TEMPORARY T" and "TABLE ACCESS FULL SYS_TEMP_0FD9D662B_2E34FB" lines. It certainly seems to be using a global temporary table.
===================== PARSING IN CURSOR #140100560521424 len=174 dep=1 uid=0 oct=1 lid=0 tim=733844612 hv=1878591410 ad='80b179f0' sqlid='40a2untrzk1xk' CREATE GLOBAL TEMPORARY T END OF STMT ... ===================== ... ===================== PARSING IN CURSOR #140100560423976 len=77 dep=0 uid=109 oct=3 lid=109 tim=733865863 hv=3518560624 ad='a35bc6c0' sqlid='9fzhbw78vjybh' WITH query1 AS ( SELECT /*+ MATERIALIZE */ * FROM t1 ) SELECT * FROM query1 END OF STMT ... STAT #140100560423976 id=1 cnt=100 pid=0 pos=1 obj=0 op='TEMP TABLE TRANSFORMATION (cr=15 pr=1 pw=1 time=19589 us)' STAT #140100560423976 id=2 cnt=0 pid=1 pos=1 obj=0 op='LOAD AS SELECT (cr=3 pr=0 pw=1 time=16243 us)' STAT #140100560423976 id=3 cnt=100 pid=2 pos=1 obj=91676 op='TABLE ACCESS FULL T1 (cr=3 pr=0 pw=0 time=1514 us cost=3 size=300 card=100)' STAT #140100560423976 id=4 cnt=100 pid=1 pos=2 obj=0 op='VIEW (cr=12 pr=1 pw=0 time=1257 us cost=2 size=1300 card=100)' STAT #140100560423976 id=5 cnt=100 pid=4 pos=1 obj=4254950955 op='TABLE ACCESS FULL SYS_TEMP_0FD9D662B_2E34FB (cr=12 pr=1 pw=0 time=1203 us cost=2 size=300 card=100)' ... =====================
Note. This is an undocumented feature. I've given you an example that uses a global temporary table, but perhaps there are other circumstances that don't.
PL/SQL Declaration Section
An Oracle Database 12c enhancement allows PL/SQL declarations in theWITHclause. This enhancement is discussed
here.
For more information see:
WITH Clause Enhancements in Oracle Database 12c Release 1 (12cR1)
subquery_factoring_clause
Hope this helps. Regards Tim...
Back to the Top.
相关文章推荐
- Oracle 11gR2 RSF(Recurive Subquery factoring)
- WITH AS短语,也叫做子查询部分(subquery factoring)
- Recursive Subquery Factoring (Recursive WITH)
- Oracle 11g R2 RSF(Recurive Subquery factoring)
- mysql笔记-[Err] 1235 - This version of MariaDB doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
- This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME subquery
- What is SUBQUERY?
- Partition-方案二:通过 Insert with a subquery 方法
- mysql 创建视图时提示View's SELECT contains a subquery in the FROM clause
- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
- Only one expression can be specified in the select list when the subquery is not introduced with EXI
- Optimizer Transformations: Subquery Unesting part 2
- 问题:MySQL doesn't yet support 'LIMIT & IN/ALL/AN Y/SOME subquery
- subquery unnesting、Subquery unnesting and View Merge
- mysql创建视图 :View's SELECT contains a subquery in the FROM clause
- correlated subquery and non-correlated subquery
- mysql error This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
- java.sql.SQLException: ORA-01799: a column may not be outer-joined to a subquery
- 报错java.sql.SQLException: Subquery returns more than 1 row
- Only one expression can be specified in the select list when the subquery is not introduced with EXI