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

有一个递归查询在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

时间: 2024-10-24 04:47:48

Oracle 11g 递归+ exists执行计划的改变的相关文章

Oracle固定SQL的执行计划(一)---SQL Profile

我们都希望对于所有在Oracle数据库中执行的SQL,CBO都能产生出正确的执行计划,但实际情况却并非如此,由于各种各样的原因(比如目标SQL所涉及的对象的统计信息的不准确,或者CBO内部一些成本计算公式的先天缺陷等),导致有时CBO产生效率不高.甚至是错误的执行计划.特别是CBO对目标SQL所产生的初始执行计划是正确的,后来由于某种原因(比如统计信息的变更等)而导致CBO重新对其产生了错误的执行计划,这种执行计划的改变往往会导致目标SQL执行时间呈数量级的递增,而且常常会让我们很困惑:这个SQ

Oracle性能优化之执行计划管理_超越OCP精通Oracle视频教程培训31

Oracle性能优化之执行计划管理_超越OCP精通Oracle视频教程培训31 本课程介绍: Oracle视频教程,风哥本套oracle教程培训<<Oracle数据库性能优化培训教程>>的第1/10套:Oracle性能优化之执行计划管理.主要学习Oracle性能优化简介,SQL 语句处理流程,软解析和硬解析,绑定变量及案例,游标的介绍,Oracle的优化器,执行计划的查看,SQL语句访问路径,SQL语句的连接方式,Oracle驱动表,执行计划的干预,常用hint提示的使用. 视频教

Oracle优化器和执行计划

1. 优化器(Optimizer)是sql分析和执行的优化工具,它负责制定sql的执行计划,负责保证sql执行效率最高,比如决定oracle以什么方式访问数据,全表扫描(full table scan)还是索引范围(index range scan)扫描,还是全索引快速扫描(index fast full scan, INDEX_FFS),对于表关联查询,是用什么方式关联.有2种优化器,RBO和CBO,从oracle 10g开始,RBO已经被弃用,但是仍可以通过hint的方式使用. 2. RBO

oracle表的统计信息完全正确,执行计划无故改变。原厂人员如是回复

就像在电话里提到的那样,Oracle内部的优化器是根据一系列的内部算法基于表上的统计信息来产生执行计划的.对于特别复杂的SQL语句,Oracle的优化器有一定几率不能得到最优的执行计划(因为机器代码实际上是比较死板的,虽然得到的执行计划按照内部的算法来看是比较快的,但是实际上这个执行计划可能在实际执行中比较慢).我们现在碰到的就是这种情况,虽然表的统计信息是准的,但恰恰优化器在基于这个统计信息使用内部算法得到的执行计划是不优化的一这是优化器的固有限制.这时候就需要DBA/Oracle Suppo

有多少办法可以查看一个Oracle SQL语句的执行计划 - SQL EXECUTE PLAN

待补充,如果要做一个SQL自动审核工具,从哪里可以下手? 1.通过SQL*PLUS工具里的EXPLAIN PLAN FOR判断,利用DBMS_XPLAN.DISPLAY显示. 2.通过SQL*PLUS工具里的 SET AUTOTRACE命令显示 3.SQL_TRACE,在数据库全局(有性能问题,基本上是废的选项),或者对当前Session定义SQL_TRACE,或者利用DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION获取其他Session的SQL_TRACE.利用TKPR

oracle性能诊断艺术-执行计划

--case1 --case2 --case3 --case4 --case5 --case6 --case7 --case8 --case9 --case10 --case12 SQL> ALTER SESSION SET statistics_level = all; --case13 --case14 --case15 --case16 --case17 --case18 --case19 --case20

Oracle 11g 执行计划管理概述

以下内容来源于:http://www.51cto.com/art/200806/76223.htm 35.2  执行计划管理 35.2.1  概述 同一SQL语句的执行计划可能因为优化器的版本.优化统计.优化参数.系统设置的不同而不同.而SQL语句的执行计划自动改变,通常情况下会带来性能提升,但是在某些情况下可能导致系统性能的下降.在11g之前,DBA使用存储大纲(Stored Outline)和SQL 概要(Profile)来固定某些SQL语句的执行计划,防止因为系统自动更改执行计划而导致的性

Oracle 11g 执行计划管理1

1. 执行计划管理的工作原理 1.1控制执行计划的稳定性 11g之前,可以使用存储大纲(stored outline)和SQL Profile来固定某条SQL语句的执行计划,防止由于执行计划发生变化而导致的性能下降. 11g开始,oracle引入了SQL执行计划管理,从而可以让系统自动的来控制SQL语句执行计划的稳定性,进而防止由于执行计划发生变化而导致的性能下降 1.2 11g执行计划管理 优化器会为所有执行次数超过一次的SQL语句维护该SQL语句的每个执行计划的历史列表(plan histo

Oracle SQL执行计划基线总结(SQL Plan Baseline)

一.基础概念 Oracle 11g开始,提供了一种新的固定执行计划的方法,即SQL plan baseline,中文名SQL执行计划基线(简称基线),可以认为是OUTLINE(大纲)或者SQL PROFILE的改进版本,基本上它的主要作用可以归纳为如下两个: 1.稳定给定SQL语句的执行计划,防止执行环境或对象统计信息等等因子的改变对SQL语句的执行计划产生影响! 2.减少数据库中出现SQL语句性能退化的概率,理论上不允许一条语句切换到一个比已经执行过的执行计划慢很多的新的执行计划上! 注意: