使用unnest Hint优化SQL

来源:互联网 发布:战舰少女r重炮改数据 编辑:程序博客网 时间:2024/04/20 00:07

下面这个SQL执行时间需要28.4分钟:

SELECT *
  FROM (SELECT ROWNUM LINE, M.*
          FROM (SELECT TO_CHAR(A.OID) OID,
                       A.REGION,
                       TO_CHAR(A.GROUPOID) GROUPOID,
                       A.MEMTYPE,
                       (SELECT DICTNAME
                          FROM DICT_ITEM
                         WHERE GROUPID = 'GroupMemberType'
                           AND DICTID = A.MEMTYPE
                       ) MEMTYPENAME,
                       A.APPLYOPERID,
                       SUBS.SUBSNAME SUBSNAME
                  FROM SUBSCRIBER SUBS, GROUP_SUBS_MEMBER A
                 WHERE SUBS.REGION(+) = 14
                   AND SUBS.ACTIVE(+) = 1
                   AND SUBS.SUBSID(+) = A.SUBSID
                   AND A.REGION = 14
                   AND A.MEMTYPE <> 9
                   AND A.STATUS = :MEMSTATUS
                   AND EXISTS
                    (SELECT 1
                          FROM GROUP_SUBS_ATTR GSA, GROUP_SUBSCRIBER GS
                         WHERE GS.CUSTID = :CUSTID
                           AND GSA.SUBSID = GS.SUBSID
                           AND GSA.ATTRID = :ATTRID
                           AND GSA.ATTRVALUE = :ATTRVALUE
                           AND A.GROUPOID = GS.SUBSID
                           AND GS.REGION = 14
                           AND GSA.REGION = 14
                           AND (GS.STATUS NOT LIKE :PSSTATUS OR GS.STATUS = :OTHERSTATUS OR GS.STATUS = :OTHERSTATUS2)
                     )
                  ORDER BY GROUPOID, MEMSERVNUMBER
                 ) M
         )
 WHERE LINE >= 0 AND LINE <= 50

执行计划如下:


从执行计划可以看出,exists子句返回的记录数较少,估值为1,实际为285。主查询返回了8755K,对exists子句做filter操作,效率是非常低的。这种情况就比较适合做unnest。在11g的版本,unnest一般情况下都是默认使用的,不知道为何在这里没有使用。

在Exists子句的select 后面加了/*+ unnest */的hint后,SQL只需要4秒钟就执行完了,为了能在sql monitor的图形页面显示,特意又在主查询的select 后面增加了 /*+ monitor */的hint,执行计划如下:




0 0