使用push_subq优化SQL

需要优化的SQL

SELECT *
  FROM (SELECT A.*, ROWNUM R
          FROM (SELECT DISTINCT A.NDOCID AS NDOCID,
                                TO_CHAR(NVL(A.DMODIFYDATE, A.DCREATEDATE),
                                        'yyyy-MM-dd hh24:mi:ss') AS DMODIFYDATE,
                                NVL(A.CURTITLE, ' ') AS CTITLE,
                                A.DMODIFYDATE AS DM,
                                A.DCREATEDATE,
                                A.CURTITLE,
                                A.NPROCID,
                                A.NPROCSTATUS,
                                A.NDOCSORTID,
                                A.NMANAGERID,
                                GW.CDOCPRIORITY,
                                GW.CFWDW,
                                GW.WENHAO,
                                GW.CDOCUTYPE,
                                COUNT(A.NDOCID) OVER() AS ROWNUMBER
                  FROM WF_DOC_GW A,
                       (SELECT NDOCID,
                               NJJCD,
                               CBT AS CTITLE,
                               CFWDW,
                               NVL(CDOCFROM, '本单位发文') AS CDOCFROM,
                               NVL(CDOCPRIORITY, 100) AS CDOCPRIORITY,
                               NVL(CFWZH, '无文号') AS WENHAO,
                               CDOCUTYPE,
                               CFWYDW
                          FROM WF_DOC_GW_SHOUWEN SW
                        UNION ALL
                        SELECT NDOCID,
                               NJJCD,
                               CBT AS CTITLE,
                               CFWDW,
                               NVL(CDOCFROM, '本单位发文') AS CDOCFROM,
                               NVL(CDOCPRIORITY, 0) AS CDOCPRIORITY,
                               NVL(CWENHAO, '无文号') AS WENHAO,
                               CDOCUTYPE,
                               CFWYDW
                          FROM WF_DOC_GW_FAWEN FW) GW
                 WHERE ((A.NPROCID = 20 AND A.NPROCSTATUS = 1) OR
                       (A.NPROCID <> 20))
                   AND (A.NSTATE = 0 OR (A.NSTATE = 2 AND A.NDOCSORTID = 1))
                   AND A.NDOCSORTID IN (1, 2)
                   AND ((INSTR(',' || A.CPROCUSERLIST || ',',
                               ',' || '4301' || ',') > 0 AND
                       A.NDOCID NOT IN
                       (SELECT GI.SRC_NDOCID
                            FROM WF_DOC_GW_INNER GI
                           WHERE GI.SRC_USERID = 4301
                             AND GI.RETURNSTATUS IS NULL
                             AND GI.SRC_NDOCID IS NOT NULL)) OR
                       A.NPROCUID = 4301)
                   AND (A.NMSGID = 0 OR
                       (A.NMSGID IS NOT NULL AND A.NFWQBOPT = 10))
                   AND GW.NDOCID = A.NDOCID
                 ORDER BY A.DMODIFYDATE DESC, GW.CDOCPRIORITY DESC) A
         WHERE ROWNUM <= 13) B
 WHERE R > 0

 执行计划

-------------------------------------------------------------------------
| Id  | Operation                         | Name               | E-Rows |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |                    |        |
|*  1 |  VIEW                             |                    |     13 |
|*  2 |   COUNT STOPKEY                   |                    |        |
|   3 |    VIEW                           |                    |    261 |
|*  4 |     SORT UNIQUE STOPKEY           |                    |    261 |
|   5 |      WINDOW BUFFER                |                    |    261 |
|*  6 |       FILTER                      |                    |        |
|*  7 |        HASH JOIN                  |                    |  90557 |
|*  8 |         TABLE ACCESS FULL         | WF_DOC_GW          |  84010 |
|   9 |         VIEW                      |                    |    261K|
|  10 |          UNION-ALL                |                    |        |
|  11 |           TABLE ACCESS FULL       | WF_DOC_GW_SHOUWEN  |    242K|
|  12 |           TABLE ACCESS FULL       | WF_DOC_GW_FAWEN    |  18876 |
|* 13 |        TABLE ACCESS BY INDEX ROWID| WF_DOC_GW_INNER    |      1 |
|* 14 |         INDEX RANGE SCAN          | IDX_INNER_SRCDOCID |      2 |
-------------------------------------------------------------------------

 
 

Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("R">0)
   2 - filter(ROWNUM<=13)
   4 - filter(ROWNUM<=13)
   6 - filter(((INSTR(','||"A"."CPROCUSERLIST"||',',',4301,')>0 AND  IS NULL) OR "A"."NPROCUID"=4301))
   8 - filter((("A"."NSTATE"=0 OR ("A"."NSTATE"=2 AND "A"."NDOCSORTID"=1)) AND ("A"."NPROCID"<>20 OR 
              ("A"."NPROCSTATUS"=1 AND "A"."NPROCID"=20)) AND ("A"."NMSGID"=0 OR ("A"."NFWQBOPT"=10 AND "A"."NMSGID" IS NOT 
              NULL)) AND INTERNAL_FUNCTION("A"."NDOCSORTID")))
  12 - access("NDOCID"="A"."NDOCID")
  14 - access("NDOCID"="A"."NDOCID")
  15 - filter(("GI"."SRC_USERID"=4301 AND "GI"."RETURNSTATUS" IS NULL))
  16 - access("GI"."SRC_NDOCID"=:B1)
       filter("GI"."SRC_NDOCID" IS NOT NULL)

该条SQL执行后的结果集只有2条数据,WF_DOC_GW_SHOUWEN数据量有24万,NDOCID是主键,从执行计划看,走的是全表扫描,和预期结果不符合,应该走的是唯一索引才对,优化的思路是先关联WF_DOC_GW和WF_DOC_GW_INNER,计算出结果集后,再关联WF_DOC_GW_SHOUWEN,这样就会走唯一索引,使用push_subq可以达到想要到想过,修改后的SQL如下

SELECT *
  FROM (SELECT A.*, ROWNUM R
          FROM (SELECT /*+ push_subq(@tmp)*/
                DISTINCT A.NDOCID AS NDOCID,
                         TO_CHAR(NVL(A.DMODIFYDATE, A.DCREATEDATE),
                                 'yyyy-MM-dd hh24:mi:ss') AS DMODIFYDATE,
                         NVL(A.CURTITLE, ' ') AS CTITLE,
                         A.DMODIFYDATE AS DM,
                         A.DCREATEDATE,
                         A.CURTITLE,
                         A.NPROCID,
                         A.NPROCSTATUS,
                         A.NDOCSORTID,
                         A.NMANAGERID,
                         GW.CDOCPRIORITY,
                         GW.CFWDW,
                         GW.WENHAO,
                         GW.CDOCUTYPE,
                         COUNT(A.NDOCID) OVER() AS ROWNUMBER
                  FROM WF_DOC_GW A,
                       (SELECT NDOCID,
                               NJJCD,
                               CBT AS CTITLE,
                               CFWDW,
                               NVL(CDOCFROM, '本单位发文') AS CDOCFROM,
                               NVL(CDOCPRIORITY, 100) AS CDOCPRIORITY,
                               NVL(CFWZH, '无文号') AS WENHAO,
                               CDOCUTYPE,
                               CFWYDW
                          FROM WF_DOC_GW_SHOUWEN SW
                        UNION ALL
                        SELECT NDOCID,
                               NJJCD,
                               CBT AS CTITLE,
                               CFWDW,
                               NVL(CDOCFROM, '本单位发文') AS CDOCFROM,
                               NVL(CDOCPRIORITY, 0) AS CDOCPRIORITY,
                               NVL(CWENHAO, '无文号') AS WENHAO,
                               CDOCUTYPE,
                               CFWYDW
                          FROM WF_DOC_GW_FAWEN FW) GW
                 WHERE ((A.NPROCID = 20 AND A.NPROCSTATUS = 1) OR
                       (A.NPROCID <> 20))
                   AND (A.NSTATE = 0 OR (A.NSTATE = 2 AND A.NDOCSORTID = 1))
                   AND A.NDOCSORTID IN (1, 2)
                   AND ((INSTR(',' || A.CPROCUSERLIST || ',',
                               ',' || '4301' || ',') > 0 AND
                       A.NDOCID NOT IN
                       (SELECT /*+ qb_name(tmp)*/
                           GI.SRC_NDOCID
                            FROM WF_DOC_GW_INNER GI
                           WHERE GI.SRC_USERID = 4301
                             AND GI.RETURNSTATUS IS NULL
                             AND GI.SRC_NDOCID IS NOT NULL)) OR
                       A.NPROCUID = 4301)
                   AND (A.NMSGID = 0 OR
                       (A.NMSGID IS NOT NULL AND A.NFWQBOPT = 10))
                   AND GW.NDOCID = A.NDOCID
                 ORDER BY A.DMODIFYDATE DESC, GW.CDOCPRIORITY DESC) A
         WHERE ROWNUM <= 13) B
 WHERE R > 0

   

------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                      |    13 |  9984 |  2518   (1)| 00:00:31 |
|*  1 |  VIEW                               |                      |    13 |  9984 |  2518   (1)| 00:00:31 |
|*  2 |   COUNT STOPKEY                     |                      |       |       |            |          |
|   3 |    VIEW                             |                      |   244 |   179K|  2518   (1)| 00:00:31 |
|*  4 |     SORT UNIQUE STOPKEY             |                      |   244 | 63928 |  2517   (1)| 00:00:31 |
|   5 |      WINDOW BUFFER                  |                      |   244 | 63928 |  2518   (1)| 00:00:31 |
|   6 |       NESTED LOOPS                  |                      |   244 | 63928 |  2516   (1)| 00:00:31 |
|*  7 |        TABLE ACCESS FULL            | WF_DOC_GW            |   242 | 27588 |  1547   (2)| 00:00:19 |
|*  8 |         TABLE ACCESS BY INDEX ROWID | WF_DOC_GW_INNER      |     1 |    17 |     2   (0)| 00:00:01 |
|*  9 |          INDEX RANGE SCAN           | IDX_INNER_SRCDOCID   |     2 |       |     1   (0)| 00:00:01 |
|  10 |        VIEW                         |                      |     1 |   148 |     4   (0)| 00:00:01 |
|  11 |         UNION ALL PUSHED PREDICATE  |                      |       |       |            |          |
|  12 |          TABLE ACCESS BY INDEX ROWID| WF_DOC_GW_SHOUWEN    |     1 |    49 |     2   (0)| 00:00:01 |
|* 13 |           INDEX UNIQUE SCAN         | PK_WF_DOC_GW_SHOUWEN |     1 |       |     1   (0)| 00:00:01 |
|  14 |          TABLE ACCESS BY INDEX ROWID| WF_DOC_GW_FAWEN      |     1 |    38 |     2   (0)| 00:00:01 |
|* 15 |           INDEX UNIQUE SCAN         | PK_WF_DOC_GW_FAWEN   |     1 |       |     1   (0)| 00:00:01 |

 

优化前的逻辑读是12000,优化后的逻辑读降到了5000,还是蛮有效果的

猜你喜欢

转载自yufeng0471.iteye.com/blog/1927111