子查询解嵌套not in 无法展开改写

SQL> explain plan for select *
  from OPS$CZTEST1.SAVJ_ATOMJOURBAK
 where ((list_flag = '1' and prt_flag = '0') and
       acct_no not in
       (select acct_no
           from OPS$CZTEST1.savb_basicinfo1
          where ((card_no is not null and base_acct_no is null) or
                (book_flag = '1' and bus_code = 21))));  2    3    4    5    6    7    8 

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3909253513

--------------------------------------------------------------------------------------
| Id  | Operation                             | Name                         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                                       | 54953 |    18M|   594M  (1)      |999:59:59 |
|*  1 |  FILTER                               |                                       |             |            |                           |          |
|*  2 |   TABLE ACCESS FULL   | SAVJ_ATOMJOUR0  | 54954 |    18M|  1042   (3)       | 00:00:13 |
|*  3 |   TABLE ACCESS FULL  | SAVB_BASICINFO1   |     1       |    73   | 11220   (1)     | 00:02:15 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM
              "OPS$CZTEST1"."SAVB_BASICINFO1" "SAVB_BASICINFO1" WHERE ("BASE_ACCT_NO" IS
              NULL AND "CARD_NO" IS NOT NULL OR "BUS_CODE"=21 AND "BOOK_FLAG"='1') AND
              LNNVL("ACCT_NO"<>:B1)))
   2 - filter("PRT_FLAG"='0' AND "LIST_FLAG"='1')
   3 - filter(("BASE_ACCT_NO" IS NULL AND "CARD_NO" IS NOT NULL OR
              "BUS_CODE"=21 AND "BOOK_FLAG"='1') AND LNNVL("ACCT_NO"<>:B1))

21 rows selected.


可以看到这里:
( NOT EXISTS (SELECT /*+ */ 0 FROM
              "OPS$CZTEST1"."SAVB_BASICINFO1" "SAVB_BASICINFO1" WHERE ("BASE_ACCT_NO" IS
              NULL AND "CARD_NO" IS NOT NULL OR "BUS_CODE"=21 AND "BOOK_FLAG"='1') AND
              LNNVL("ACCT_NO"<>:B1)))

子查询没有展开,FILTER 循环类似于NL循环,会导致表SAVB_BASICINFO1访问多次,not in 可以改写成左关联的形式,改写如下:
SQL> explain plan for select count(*)
  from OPS$CZTEST1.SAVJ_ATOMJOURBAK a,
       (select acct_no
          from OPS$CZTEST1.savb_basicinfo1
         where (card_no is not null and base_acct_no is null)
        or
          (book_flag = '1' and bus_code = 21)) b
 where a.list_flag = '1'
   and a.prt_flag = '0'
   and a.acct_no = b.acct_no(+)
   and b.acct_no is null;  2    3    4    5    6    7    8    9   10   11  

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4182698075

-----------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                          | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                                       |     1      |   110 |       | 13060   (1)| 00:02:37 |
|   1 |  SORT AGGREGATE        |                                      |     1       |   110 |       |            |          |
|*  2 |   HASH JOIN ANTI            |                                     |             1 |   110 |  2632K| 13060   (1)| 00:02:37 |
|*  3 |    TABLE ACCESS FULL | SAVJ_ATOMJOUR0  | 54954 |  1985K|       |  1041   (2)| 00:00:13 |
|*  4 |    TABLE ACCESS FULL | SAVB_BASICINFO1 |   166K|    11M|       | 11216   (1)| 00:02:15 |
-----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("ACCT_NO"="ACCT_NO")
   3 - filter("PRT_FLAG"='0' AND "LIST_FLAG"='1')
   4 - filter("BASE_ACCT_NO" IS NULL AND "CARD_NO" IS NOT NULL OR "BUS_CODE"=21 AND
              "BOOK_FLAG"='1')

19 rows selected.

 

 

 


 

posted @ 2013-12-04 15:07  czcb  阅读(579)  评论(0编辑  收藏  举报