当前位置: 代码迷 >> SQL >> 施用push_subq优化SQL
  详细解决方案

施用push_subq优化SQL

热度:15   发布时间:2016-05-05 12:06:48.0
使用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,还是蛮有效果的

  相关解决方案