Oracle 11g 递归+ exists执行计划的改变

Linux大全评论311 views阅读模式

有一个递归查询在Oracle 10g上运行很快,但在11g上运行不出来。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

SQL> set timing on
SQL> set autotrace trace exp;--由于SQL执行出来需要两小时,所以就不执行了
SQL> SELECT *
      FROM (SELECT DISTINCT A.*
              FROM GG_MATERIAL_CLASSIFY A
            CONNECT BY PRIOR PARENT_CLASSIFY_ID = CLASSIFY_ID
              START WITH exists
                        (SELECT DISTINCT M.CLASSIFY_ID
                            FROM GG_DISTRIBUTION D, GG_MATERIAL M
                          WHERE D.MATERIAL_ID = M.MATERIAL_ID
                            AND A.CLASSIFY_ID=M.CLASSIFY_ID
                            AND D.ACTUAL_QTY > 0
                            AND D.DATA_AREA LIKE '03%')) B
      WHERE B.PARENT_CLASSIFY_ID = '201'
      ORDER BY B.CODE ASC;
执行计划
----------------------------------------------------------
Plan hash value: 3402505179
----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name                          | Rows  | Bytes | Cost (%CPU)| Time    | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------------------
|  0 | CREATE TABLE STATEMENT                      |                                |    68 | 27608 |  2433  (2)| 00:00:30 |      |      |
|  0 | SELECT STATEMENT                            |                                |    2 |  2174 |    15  (7)| 00:00:01 |      |      |
|  1 |  LOAD AS SELECT                            | A0K_GG_MATERIAL_PAYMENT_140122 |      |      |            |          |      |      |
|  1 |  SORT ORDER BY                              |                                |    2 |  2174 |    15  (7)| 00:00:01 |      |      |
|*  2 |  TABLE ACCESS FULL                        | GG_MATERIAL_PAYMENT            |    68 | 27608 |  2431  (2)| 00:00:30 |      |      |
|*  2 |  VIEW                                      |                                |    2 |  2174 |    15  (7)| 00:00:01 |      |      |
|  3 |    HASH UNIQUE                              |                                |    2 |  412 |    15  (7)| 00:00:01 |      |      |
|*  4 |    CONNECT BY NO FILTERING WITH SW (UNIQUE)|                                |      |      |            |          |      |      |
|  5 |      TABLE ACCESS FULL                      | GG_MATERIAL_CLASSIFY          |  1864 |  262K|    14  (0)| 00:00:01 |      |      |
|*  6 |      HASH JOIN                              |                                |    1 |    65 |  207  (0)| 00:00:03 |      |      |
|  7 |      TABLE ACCESS BY INDEX ROWID          | GG_MATERIAL                    |    72 |  1512 |    24  (0)| 00:00:01 |      |      |
|*  8 |        INDEX RANGE SCAN                    | RELATIONSHIP_84_FK            |    72 |      |    3  (0)| 00:00:01 |      |      |
|*  9 |      TABLE ACCESS BY GLOBAL INDEX ROWID    | GG_DISTRIBUTION                |  1624 | 35728 |  183  (0)| 00:00:03 | ROWID | ROWID |
|* 10 |        INDEX RANGE SCAN                    | IX_DISTRIBU_ACT_QTY01          |  144K|      |    6  (0)| 00:00:01 |      |      |
----------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - filter("GG_MATERIAL_PAYMENT"."PAYMENT_AMOUNT" IS NULL)
  2 - filter("B"."PARENT_CLASSIFY_ID"='201')
  4 - access("CLASSIFY_ID"=PRIOR "PARENT_CLASSIFY_ID")
      filter( EXISTS (SELECT 0 FROM "GG_MATERIAL" "M","GG_DISTRIBUTION" "D" WHERE "D"."ACTUAL_QTY">0 AND "D"."DATA_AREA" LIKE '03%'
              AND "M"."CLASSIFY_ID"=:B1 AND "D"."MATERIAL_ID"="M"."MATERIAL_ID"))
  6 - access("D"."MATERIAL_ID"="M"."MATERIAL_ID")
  8 - access("M"."CLASSIFY_ID"=:B1)
  9 - filter("D"."DATA_AREA" LIKE '03%')
  10 - access("D"."ACTUAL_QTY">0)
--网络上提供的方法1:修改隐含参数
SQL> alter session set "_optimizer_connect_by_elim_dups" = false;
SQL> alter session set "_connect_by_use_union_all" = "old_plan_mode";
SQL> SELECT *
  2        FROM (SELECT DISTINCT A.*
  3                FROM GG_MATERIAL_CLASSIFY A
  4              CONNECT BY PRIOR PARENT_CLASSIFY_ID = CLASSIFY_ID
  5                START WITH exists
  6                          (SELECT DISTINCT M.CLASSIFY_ID
  7                              FROM GG_DISTRIBUTION D, GG_MATERIAL M
  8                            WHERE D.MATERIAL_ID = M.MATERIAL_ID
  9                              AND A.CLASSIFY_ID=M.CLASSIFY_ID
 10                              AND D.ACTUAL_QTY > 0
 11                              AND D.DATA_AREA LIKE '03%')) B
 12        WHERE B.PARENT_CLASSIFY_ID = '201'
 13        ORDER BY B.CODE ASC;
已选择11行。
已用时间:  00: 00: 04.39
执行计划
----------------------------------------------------------
Plan hash value: 3792201725
----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time    | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT                          |                          |    1 |  1087 |      |    3  (34)| 00:00:01 |      |      |
|  1 |  SORT ORDER BY                            |                          |    1 |  1087 |      |    3  (34)| 00:00:01 |      |      |
|*  2 |  VIEW                                    |                          |    1 |  1087 |      |    3  (34)| 00:00:01 |      |      |
|  3 |    HASH UNIQUE                            |                          |    1 |  144 |      |    3  (34)| 00:00:01 |      |      |
|*  4 |    CONNECT BY WITH FILTERING            |                          |      |      |      |            |          |      |      |
|  5 |      TABLE ACCESS BY INDEX ROWID          | GG_MATERIAL_CLASSIFY    |      |      |      |            |          |      |      |
|*  6 |      HASH JOIN                          |                          |  114K|  5816K|      | 16615  (1)| 00:03:20 |      |      |
|  7 |        INDEX FAST FULL SCAN              | PK_GG_MATERIAL_CLASSIFY  |  1864 | 16776 |      |    3  (0)| 00:00:01 |      |      |
|*  8 |        HASH JOIN                          |                          |  144K|  6051K|  3784K| 16610  (1)| 00:03:20 |      |      |
|  9 |        INDEX FAST FULL SCAN              | INX_GG_MATERIAL_CLASSIFY |  117K|  2403K|      |  145  (2)| 00:00:02 |      |      |
|* 10 |        TABLE ACCESS BY GLOBAL INDEX ROWID| GG_DISTRIBUTION          |  144K|  3097K|      | 16045  (1)| 00:03:13 | ROWID | ROWID |
|* 11 |          INDEX RANGE SCAN                | IX_DISTRIBU_ACT_QTY01    |  144K|      |      |  346  (1)| 00:00:05 |      |      |
|  12 |      NESTED LOOPS                        |                          |      |      |      |            |          |      |      |
|  13 |      CONNECT BY PUMP                    |                          |      |      |      |            |          |      |      |
|  14 |      TABLE ACCESS BY INDEX ROWID        | GG_MATERIAL_CLASSIFY    |    1 |  144 |      |    2  (0)| 00:00:01 |      |      |
|* 15 |        INDEX UNIQUE SCAN                  | PK_GG_MATERIAL_CLASSIFY  |    1 |      |      |    1  (0)| 00:00:01 |      |      |
----------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - filter("B"."PARENT_CLASSIFY_ID"='201')
  4 - access("CLASSIFY_ID"=PRIOR "PARENT_CLASSIFY_ID")
  6 - access("A"."CLASSIFY_ID"="M"."CLASSIFY_ID")
  8 - access("D"."MATERIAL_ID"="M"."MATERIAL_ID")
  10 - filter("D"."DATA_AREA" LIKE '03%')
  11 - access("D"."ACTUAL_QTY">0)
  15 - access("CLASSIFY_ID"=PRIOR "PARENT_CLASSIFY_ID")
--网络上提供的方法2:失效,执行不出来(注意,要换一个session执行)
SELECT *
      FROM (SELECT /*+ connect_by_filtering */DISTINCT A.*
              FROM GG_MATERIAL_CLASSIFY A
            CONNECT BY PRIOR PARENT_CLASSIFY_ID = CLASSIFY_ID
              START WITH exists
                        (SELECT DISTINCT M.CLASSIFY_ID
                            FROM GG_DISTRIBUTION D, GG_MATERIAL M
                          WHERE D.MATERIAL_ID = M.MATERIAL_ID
                            AND A.CLASSIFY_ID=M.CLASSIFY_ID
                            AND D.ACTUAL_QTY > 0
                            AND D.DATA_AREA LIKE '03%')) B
      WHERE B.PARENT_CLASSIFY_ID = '201'
      ORDER BY B.CODE ASC; 
  对网络的方法总结,最好不要修改隐含参数,最多加上Hint,但Hint失效,所以再去找其他的方法。

  无意之中把exits改为了in,问题解决了。
SQL> set autotrace traceonly
SQL> SELECT *
      FROM (SELECT DISTINCT A.*
              FROM GG_MATERIAL_CLASSIFY A
            CONNECT BY PRIOR PARENT_CLASSIFY_ID = CLASSIFY_ID
            START WITH CLASSIFY_ID IN
                        (SELECT DISTINCT M.CLASSIFY_ID
                          FROM GG_DISTRIBUTION D, GG_MATERIAL M
                          WHERE D.MATERIAL_ID = M.MATERIAL_ID
                            AND D.ACTUAL_QTY > 0
                            AND D.DATA_AREA LIKE '03%')) B
    WHERE B.PARENT_CLASSIFY_ID = '201'
    ORDER BY B.CODE ASC;
已选择11行。
已用时间:  00: 00: 01.00
执行计划
----------------------------------------------------------
Plan hash value: 4133877384
------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                      | Rows  | Bytes |TempSpc| Cost (%CPU)| Time    | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------------------------------
|  0 | CREATE TABLE STATEMENT                    |                            |  645K|    57M|      |  3895  (1)| 00:00:47 |      |      |
|  0 | SELECT STATEMENT                          |                            |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|  1 |  LOAD AS SELECT                          | A2K_GG_INVOICE_ITEM_140106 |      |      |      |            |          |      |      |
|  1 |  SORT ORDER BY                            |                            |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|  2 |  TABLE ACCESS FULL                      | GG_INVOICE_ITEM            |  645K|    57M|      |  1984  (2)| 00:00:24 |      |      |
|*  2 |  VIEW                                    |                            |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|  3 |    HASH UNIQUE                            |                            |  3246 |  653K|      | 16641  (1)| 00:03:20 |      |      |
|*  4 |    CONNECT BY WITHOUT FILTERING (UNIQUE) |                            |      |      |      |            |          |      |      |
|*  5 |      HASH JOIN SEMI                      |                            |  1623 |  256K|      | 16626  (1)| 00:03:20 |      |      |
|  6 |      TABLE ACCESS FULL                  | GG_MATERIAL_CLASSIFY      |  1864 |  262K|      |    14  (0)| 00:00:01 |      |      |
|  7 |      VIEW                                | VW_NSO_1                  |  144K|  2533K|      | 16610  (1)| 00:03:20 |      |      |
|*  8 |        HASH JOIN                          |                            |  144K|  6051K|  3784K| 16610  (1)| 00:03:20 |      |      |
|  9 |        INDEX FAST FULL SCAN              | INX_GG_MATERIAL_CLASSIFY  |  117K|  2403K|      |  145  (2)| 00:00:02 |      |      |
|* 10 |        TABLE ACCESS BY GLOBAL INDEX ROWID| GG_DISTRIBUTION            |  144K|  3097K|      | 16045  (1)| 00:03:13 | ROWID | ROWID |
|* 11 |          INDEX RANGE SCAN                | IX_DISTRIBU_ACT_QTY01      |  144K|      |      |  346  (1)| 00:00:05 |      |      |
|  12 |      TABLE ACCESS FULL                    | GG_MATERIAL_CLASSIFY      |  1864 |  262K|      |    14  (0)| 00:00:01 |      |      |
------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - filter("B"."PARENT_CLASSIFY_ID"='201')
  4 - access("CLASSIFY_ID"=PRIOR "PARENT_CLASSIFY_ID")
  5 - access("CLASSIFY_ID"="CLASSIFY_ID")
  8 - access("D"."MATERIAL_ID"="M"."MATERIAL_ID")
  10 - filter("D"."DATA_AREA" LIKE '03%')
  11 - access("D"."ACTUAL_QTY">0)
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
    113928  consistent gets
          0  physical reads
          0  redo size
      1960  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client

  我看了一下in 和 exists产生执行计划的区别,从谓词从看到exists需要没有展开,所以我加了一个Hint验证了一下,执行结果跟in就是一样的了。
--unnest为展开子查询
SQL> SELECT *
  FROM (SELECT DISTINCT A.*
          FROM GG_MATERIAL_CLASSIFY A
        CONNECT BY PRIOR PARENT_CLASSIFY_ID = CLASSIFY_ID
          START WITH exists
                    (SELECT /*+unnest*/DISTINCT M.CLASSIFY_ID
                        FROM GG_DISTRIBUTION D, GG_MATERIAL M
                      WHERE D.MATERIAL_ID = M.MATERIAL_ID
                        AND A.CLASSIFY_ID=M.CLASSIFY_ID
                        AND D.ACTUAL_QTY > 0
                        AND D.DATA_AREA LIKE '03%')) B
  WHERE B.PARENT_CLASSIFY_ID = '201'
  ORDER BY B.CODE ASC;
已选择11行。
已用时间:  00: 00: 01.18
执行计划
----------------------------------------------------------
Plan hash value: 2653190462
----------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                | Name                    | Rows  | Bytes |TempSpc| Cost (%CPU)| Time    | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT                          |                          |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|  1 |  SORT ORDER BY                            |                          |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|*  2 |  VIEW                                    |                          |  3246 |  3445K|      | 16641  (1)| 00:03:20 |      |      |
|  3 |    HASH UNIQUE                            |                          |  3246 |  653K|      | 16641  (1)| 00:03:20 |      |      |
|*  4 |    CONNECT BY WITHOUT FILTERING (UNIQUE) |                          |      |      |      |            |          |      |      |
|*  5 |      HASH JOIN SEMI                      |                          |  1623 |  256K|      | 16626  (1)| 00:03:20 |      |      |
|  6 |      TABLE ACCESS FULL                  | GG_MATERIAL_CLASSIFY    |  1864 |  262K|      |    14  (0)| 00:00:01 |      |      |
|  7 |      VIEW                                | VW_SQ_1                  |  144K|  2533K|      | 16610  (1)| 00:03:20 |      |      |
|*  8 |        HASH JOIN                          |                          |  144K|  6051K|  3784K| 16610  (1)| 00:03:20 |      |      |
|  9 |        INDEX FAST FULL SCAN              | INX_GG_MATERIAL_CLASSIFY |  117K|  2403K|      |  145  (2)| 00:00:02 |      |      |
|* 10 |        TABLE ACCESS BY GLOBAL INDEX ROWID| GG_DISTRIBUTION          |  144K|  3097K|      | 16045  (1)| 00:03:13 | ROWID | ROWID |
|* 11 |          INDEX RANGE SCAN                | IX_DISTRIBU_ACT_QTY01    |  144K|      |      |  346  (1)| 00:00:05 |      |      |
|  12 |      TABLE ACCESS FULL                    | GG_MATERIAL_CLASSIFY    |  1864 |  262K|      |    14  (0)| 00:00:01 |      |      |
----------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
  2 - filter("B"."PARENT_CLASSIFY_ID"='201')
  4 - access("CLASSIFY_ID"=PRIOR "PARENT_CLASSIFY_ID")
  5 - access("A"."CLASSIFY_ID"="ITEM_0")
  8 - access("D"."MATERIAL_ID"="M"."MATERIAL_ID")
  10 - filter("D"."DATA_AREA" LIKE '03%')
  11 - access("D"."ACTUAL_QTY">0)
统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
    113928  consistent gets
          0  physical reads
          0  redo size
      1960  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          3  sorts (memory)
          0  sorts (disk)
        11  rows processed

在CentOS 6.4下安装Oracle 11gR2(x64) http://www.linuxidc.com/Linux/2014-02/97374.htm

Oracle 11gR2 在VMWare虚拟机中安装步骤 http://www.linuxidc.com/Linux/2013-09/89579p2.htm

Debian 下 安装 Oracle 11g XE R2 http://www.linuxidc.com/Linux/2014-03/98881.htm

Oracle性能优化 之 共享池 http://www.linuxidc.com/Linux/2012-02/54062.htm

企鹅博客
  • 本文由 发表于 2020年10月6日 00:34:02
  • 转载请务必保留本文链接:https://www.qieseo.com/190555.html

发表评论