查询转换——视图合并(1)!

查询转换的主要目的就是确定如果改变查询的写法会不会提供更好的查询计划。查询转换能够并且可能会重写你的查询。查询转换器可能会改变你最初所写查询的结构,只要这样的改变不会影响结果集。

视图合并是一种将内嵌或存储试视图展开为能够独立分析或者与查询剩余部分合并成总体执行计划的独立查询块的转换。

/*+ NO_QUERY_TRANSFORMATION */   禁止查询转换。

/*+ MERGE(TABLE) */     能够对视图的各个查询进行相应的合并。
/*+ NO_MERGE(TABLE) */  对于有可合并的视图不再合并。

  1. QL> select /*+ gather_plan_statistics */  
  2.   2   e.empno, e.ename, e.sal, v.avg_sal  
  3.   3    from emp e,  
  4.   4         (select emp.deptno, round(avg(emp.sal), 2) avg_sal  
  5.   5            from emp  
  6.   6           group by emp.deptno) v  
  7.   7   where e.deptno = v.deptno  
  8.   8     and e.sal > v.avg_sal;  
  9.   
  10.      EMPNO ENAME             SAL    AVG_SAL  
  11. ---------- ---------- ---------- ----------  
  12.       7499 ALLEN            1600    1566.67  
  13.       7566 JONES            2975       2175  
  14.       7698 BLAKE            2850    1566.67  
  15.       7788 SCOTT            3000       2175  
  16.       7839 KING             5000    2916.67  
  17.       7902 FORD             3000       2175  
  18.   
  19. 已选择6行。  
  20.   
  21. SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));  
  22.   
  23. PLAN_TABLE_OUTPUT  
  24. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  25. SQL_ID  1hjw7xx9h3fr2, child number 0  
  26. -------------------------------------  
  27. select /*+ gather_plan_statistics */  e.empno, e.ename, e.sal,  
  28. v.avg_sal   from emp e,        (select emp.deptno, round(avg(emp.sal),  
  29. 2) avg_sal           from emp          group by emp.deptno) v  where  
  30. e.deptno = v.deptno    and e.sal > v.avg_sal  
  31.   
  32. Plan hash value: 269884559  
  33.   
  34. ------------------------------------------------------------------------------------------------------------------  
  35. | Id  | Operation            | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |  
  36.   
  37. PLAN_TABLE_OUTPUT  
  38. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  39. ------------------------------------------------------------------------------------------------------------------  
  40. |   0 | SELECT STATEMENT     |      |      1 |        |      6 |00:00:00.01 |      15 |       |       |          |  
  41. |*  1 |  HASH JOIN           |      |      1 |      1 |      6 |00:00:00.01 |      15 |   951K|   951K|  605K (0)|  
  42. |   2 |   VIEW               |      |      1 |      3 |      3 |00:00:00.01 |       7 |       |       |          |  
  43. |   3 |    HASH GROUP BY     |      |      1 |      3 |      3 |00:00:00.01 |       7 |   778K|   778K| 1179K (0)|  
  44. |   4 |     TABLE ACCESS FULL| EMP  |      1 |     14 |     14 |00:00:00.01 |       7 |       |       |          |  
  45. |   5 |   TABLE ACCESS FULL  | EMP  |      1 |     14 |     14 |00:00:00.01 |       8 |       |       |          |  
  46. ------------------------------------------------------------------------------------------------------------------  
  47.   
  48. Predicate Information (identified by operation id):  
  49. ---------------------------------------------------  
  50.   
  51. PLAN_TABLE_OUTPUT  
  52. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  53.   
  54.    1 - access("E"."DEPTNO"="V"."DEPTNO")  
  55.        filter("E"."SAL">"V"."AVG_SAL")  
  56.   
  57.   
  58. 已选择26行。  

上面是默认的执行计划,使用VIEW关键字来表明视图是保持原样的

  1. SQL> set linesize 150  
  2. SQL> set serveroutput off;  
  3. SQL> select /*+ gather_plan_statistics no_merge(v) */  
  4.   2   e.empno, e.ename, e.sal, v.avg_sal  
  5.   3    from emp e,  
  6.   4         (select emp.deptno, round(avg(emp.sal), 2) avg_sal  
  7.   5            from emp  
  8.   6           group by emp.deptno) v  
  9.   7   where e.deptno = v.deptno  
  10.   8     and e.sal > v.avg_sal;  
  11.   
  12.      EMPNO ENAME             SAL    AVG_SAL  
  13. ---------- ---------- ---------- ----------  
  14.       7499 ALLEN            1600    1566.67  
  15.       7566 JONES            2975       2175  
  16.       7698 BLAKE            2850    1566.67  
  17.       7788 SCOTT            3000       2175  
  18.       7839 KING             5000    2916.67  
  19.       7902 FORD             3000       2175  
  20.   
  21. 已选择6行。  
  22.   
  23. SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));  
  24.   
  25. PLAN_TABLE_OUTPUT  
  26. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  27. SQL_ID  48rcfq057xujt, child number 0  
  28. -------------------------------------  
  29. select /*+ gather_plan_statistics no_merge(v) */  e.empno, e.ename,  
  30. e.sal, v.avg_sal   from emp e,        (select emp.deptno,  
  31. round(avg(emp.sal), 2) avg_sal           from emp          group by  
  32. emp.deptno) v  where e.deptno = v.deptno    and e.sal > v.avg_sal  
  33.   
  34. Plan hash value: 269884559  
  35.   
  36. ------------------------------------------------------------------------------------------------------------------  
  37. | Id  | Operation            | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |  
  38.   
  39. PLAN_TABLE_OUTPUT  
  40. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  41. ------------------------------------------------------------------------------------------------------------------  
  42. |   0 | SELECT STATEMENT     |      |      1 |        |      6 |00:00:00.02 |      15 |       |       |          |  
  43. |*  1 |  HASH JOIN           |      |      1 |      1 |      6 |00:00:00.02 |      15 |   951K|   951K|  598K (0)|  
  44. |   2 |   VIEW               |      |      1 |      3 |      3 |00:00:00.01 |       7 |       |       |          |  
  45. |   3 |    HASH GROUP BY     |      |      1 |      3 |      3 |00:00:00.01 |       7 |   778K|   778K| 1187K (0)|  
  46. |   4 |     TABLE ACCESS FULL| EMP  |      1 |     14 |     14 |00:00:00.01 |       7 |       |       |          |  
  47. |   5 |   TABLE ACCESS FULL  | EMP  |      1 |     14 |     14 |00:00:00.01 |       8 |       |       |          |  
  48. ------------------------------------------------------------------------------------------------------------------  
  49.   
  50. Predicate Information (identified by operation id):  
  51. ---------------------------------------------------  
  52.   
  53. PLAN_TABLE_OUTPUT  
  54. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  55.   
  56.    1 - access("E"."DEPTNO"="V"."DEPTNO")  
  57.        filter("E"."SAL">"V"."AVG_SAL")  
  58.   
  59.   
  60. 已选择26行。  

使用no_merge跟默认情况下是一样的执行计划。

  1. SQL>  e.empno, e.ename, e.sal, v.avg_sal  
  2. select /*+ gather_plan_statistics merge(v) */  
  3.   2   e.empno, e.ename, e.sal, v.avg_sal  
  4.   3    from emp e,  
  5.   4         (select emp.deptno, round(avg(emp.sal), 2) avg_sal  
  6.   5            from emp  
  7.   6           group by emp.deptno) v  
  8.   7   where e.deptno = v.deptno  
  9.   8     and e.sal > v.avg_sal;  
  10.   
  11.      EMPNO ENAME             SAL    AVG_SAL  
  12. ---------- ---------- ---------- ----------  
  13.       7788 SCOTT            3000       2175  
  14.       7566 JONES            2975       2175  
  15.       7698 BLAKE            2850    1566.67  
  16.       7839 KING             5000    2916.67  
  17.       7902 FORD             3000       2175  
  18.       7499 ALLEN            1600    1566.67  
  19.   
  20. 已选择6行。  
  21.   
  22. SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));  
  23.   
  24. PLAN_TABLE_OUTPUT  
  25. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  26. SQL_ID  g3r5cu2hg0h1a, child number 0  
  27. -------------------------------------  
  28. select /*+ gather_plan_statistics merge(v) */  e.empno, e.ename, e.sal,  
  29. v.avg_sal   from emp e,        (select emp.deptno, round(avg(emp.sal),  
  30. 2) avg_sal           from emp          group by emp.deptno) v  where  
  31. e.deptno = v.deptno    and e.sal > v.avg_sal  
  32.   
  33. Plan hash value: 2435006919  
  34.   
  35. ------------------------------------------------------------------------------------------------------------------  
  36. | Id  | Operation            | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |  
  37.   
  38. PLAN_TABLE_OUTPUT  
  39. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  40. ------------------------------------------------------------------------------------------------------------------  
  41. |   0 | SELECT STATEMENT     |      |      1 |        |      6 |00:00:00.01 |      14 |       |       |          |  
  42. |*  1 |  FILTER              |      |      1 |        |      6 |00:00:00.01 |      14 |       |       |          |  
  43. |   2 |   HASH GROUP BY      |      |      1 |      4 |     14 |00:00:00.01 |      14 |   736K|   736K| 1023K (0)|  
  44. |*  3 |    HASH JOIN         |      |      1 |     65 |     70 |00:00:00.01 |      14 |   791K|   791K|  614K (0)|  
  45. |   4 |     TABLE ACCESS FULL| EMP  |      1 |     14 |     14 |00:00:00.01 |       7 |       |       |          |  
  46. |   5 |     TABLE ACCESS FULL| EMP  |      1 |     14 |     14 |00:00:00.01 |       7 |       |       |          |  
  47. ------------------------------------------------------------------------------------------------------------------  
  48.   
  49. Predicate Information (identified by operation id):  
  50. ---------------------------------------------------  
  51.   
  52. PLAN_TABLE_OUTPUT  
  53. ------------------------------------------------------------------------------------------------------------------------------------------------------  
  54.   
  55.    1 - filter("E"."SAL">ROUND(SUM("EMP"."SAL")/COUNT("EMP"."SAL"),2))  
  56.    3 - access("E"."DEPTNO"="EMP"."DEPTNO")  
  57.   
  58.   
  59. 已选择26行。  

可以看见这里执行计划和前面不一样了,注意A-Rows列,可以看出成本比前面视图不转换高,所以CBO还是聪明的,选择了对的执行计划。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谭祖爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值