使用with子句优化代码中重复查询

Posted ClarkYu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用with子句优化代码中重复查询相关的知识,希望对你有一定的参考价值。

/*
好处: 1. 性能更好,一份复制(类似SYS_TMP...),多份使用。
       2. 结构清晰,预先定义。
       3. 代码修改不必修改多处。
       
请注意观察语句1和语句2执行计划的差异,尤其是语句2的SYS_TEMP_0FD9D6605_3B91BA4这些奇怪的命名。其实这就表示是
复制在内存中的数据,一次复制,多次使用。
       
*/


          
drop table t_with;
CREATE TABLE T_WITH AS SELECT ROWNUM ID, A.* FROM DBA_SOURCE A WHERE ROWNUM < 100001;
SET autotrace traceonly
Set linesize 1000


--语句1
SELECT ID, NAME FROM T_WITH
WHERE ID IN 
(SELECT MAX(ID) FROM T_WITH 
 UNION ALL
 SELECT MIN(ID) FROM T_WITH
 UNION ALL
 SELECT TRUNC(AVG(ID)) FROM T_WITH);
执行计划
----------------------------------------------------------------------------------
Plan hash value: 647530712
-----------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     3 |   129 |  1382   (1)| 00:00:17 |
|*  1 |  HASH JOIN             |          |     3 |   129 |  1382   (1)| 00:00:17 |
|   2 |   VIEW                 | VW_NSO_1 |     3 |    39 |  1035   (1)| 00:00:13 |
|   3 |    HASH UNIQUE         |          |     3 |    39 |  1035  (67)| 00:00:13 |
|   4 |     UNION-ALL          |          |       |       |            |          |
|   5 |      SORT AGGREGATE    |          |     1 |    13 |            |          |
|   6 |       TABLE ACCESS FULL| T_WITH   | 91060 |  1156K|   345   (1)| 00:00:05 |
|   7 |      SORT AGGREGATE    |          |     1 |    13 |            |          |
|   8 |       TABLE ACCESS FULL| T_WITH   | 91060 |  1156K|   345   (1)| 00:00:05 |
|   9 |      SORT AGGREGATE    |          |     1 |    13 |            |          |
|  10 |       TABLE ACCESS FULL| T_WITH   | 91060 |  1156K|   345   (1)| 00:00:05 |
|  11 |   TABLE ACCESS FULL    | T_WITH   | 91060 |  2667K|   345   (1)| 00:00:05 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("ID"="MAX(ID)")
Note
-----
   - dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       4969  consistent gets
          0  physical reads
          0  redo size
        558  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          3  rows processed




--语句2
WITH AGG AS (SELECT MAX(ID) MAX, MIN(ID) MIN, TRUNC(AVG(ID)) AVG FROM T_WITH)
 SELECT ID, NAME FROM T_WITH 
 WHERE ID IN 
 ( SELECT MAX FROM AGG  UNION ALL  SELECT MIN FROM AGG  UNION ALL  SELECT AVG FROM AGG);
执行计划
--------------------------------------------------------------------------------------------------------
Plan hash value: 3705751949
---------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name                       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                            |     3 |   129 |   697   (1)| 00:00:09 |
|   1 |  TEMP TABLE TRANSFORMATION |                            |       |       |            |          |
|   2 |   LOAD AS SELECT           | SYS_TEMP_0FD9D6605_3B91BA4 |       |       |            |          |
|   3 |    SORT AGGREGATE          |                            |     1 |    13 |            |          |
|   4 |     TABLE ACCESS FULL      | T_WITH                     | 91060 |  1156K|   345   (1)| 00:00:05 |
|*  5 |   HASH JOIN                |                            |     3 |   129 |   352   (1)| 00:00:05 |
|   6 |    VIEW                    | VW_NSO_1                   |     3 |    39 |     6   (0)| 00:00:01 |
|   7 |     HASH UNIQUE            |                            |     3 |    39 |     6  (67)| 00:00:01 |
|   8 |      UNION-ALL             |                            |       |       |            |          |
|   9 |       VIEW                 |                            |     1 |    13 |     2   (0)| 00:00:01 |
|  10 |        TABLE ACCESS FULL   | SYS_TEMP_0FD9D6605_3B91BA4 |     1 |    13 |     2   (0)| 00:00:01 |
|  11 |       VIEW                 |                            |     1 |    13 |     2   (0)| 00:00:01 |
|  12 |        TABLE ACCESS FULL   | SYS_TEMP_0FD9D6605_3B91BA4 |     1 |    13 |     2   (0)| 00:00:01 |
|  13 |       VIEW                 |                            |     1 |    13 |     2   (0)| 00:00:01 |
|  14 |        TABLE ACCESS FULL   | SYS_TEMP_0FD9D6605_3B91BA4 |     1 |    13 |     2   (0)| 00:00:01 |
|  15 |    TABLE ACCESS FULL       | T_WITH                     | 91060 |  2667K|   345   (1)| 00:00:05 |
---------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   5 - access("ID"="MAX")
Note
-----
   - dynamic sampling used for this statement (level=2)
统计信息
----------------------------------------------------------
          2  recursive calls
          8  db block gets
       2496  consistent gets
          1  physical reads
        600  redo size
        558  bytes sent via SQL*Net to client
        415  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          3  rows processed

以上是关于使用with子句优化代码中重复查询的主要内容,如果未能解决你的问题,请参考以下文章

海量语句查询代码优化

优化广泛使用 IN 子句的 Oracle SQL 查询

sql面试题_SQl优化技巧_1注意通配符中like的使用,百分号放后面_2避免在where子句中对字段进行函数操作_3在子查询当中,尽量用exists代替in_4where子句中尽量不要使用(代码片

查询运行时间过长,如何优化?

sql优化

oracle查询的查询优化