ITPub博客

首页 > 数据库 > Oracle > 第87期 Oracle执行计划,彻底搞懂Oracle的执行计划 II

第87期 Oracle执行计划,彻底搞懂Oracle的执行计划 II

原创 Oracle 作者:pxbibm 时间:2026-10-29 12:28:33 0 删除 编辑

在上一篇《第86期 Oracle执行计划,彻底搞懂Oracle的执行计划》中,我们学习了以下操作:

- 展示 SQL 语句**实际(TYPICAL 模式)**执行计划,包含基数预估与成本值。

- 通过 GATHER_PLAN_STATISTICS Hint,展示 SQL 语句**实际(ALLSTATS LAST 模式)**执行计划,用来对比预估基数和计划里每一步操作返回的真实行数,同时获取语句最终实际执行时间(中间步骤的耗时不一定贴近真实耗时)。

- 在会话级别将 STATISTICS_LEVEL 参数设置为 ALL,展示 SQL 语句**实际(ALLSTATS LAST 模式)**执行计划,可以拿到最终执行时间,并且中间步骤的耗时估算也更加贴近真实值(部分场景下,SQL 整体执行耗时会明显上升)。

- 在 ALL_ROWS、FIRST_ROWS_1、CHOOSE 之间切换 OPTIMIZER_MODE 参数,对比实际执行计划的变化。注意:将优化器模式设置为 FIRST_ROWS_1 时,优化器可能低估返回行数,执行计划中就能观察到这个现象。

- 使用 SQL*Plus 的 AUTOTRACE 和 EXPLAIN PLAN 展示一份看似正确的执行计划,并探究依赖这类计划时可能遇到的各类问题。

- 观察绑定变量窥视(bind peeking)对执行计划带来的影响。

- 通过设置 10132 事件来获取执行计划。

- 直接从 10046 跟踪文件中读取执行计划。

- 使用 TKPROF 工具处理跟踪文件,同时了解让 TKPROF 生成 Explain 计划时会引发的一个典型隐患。

那么还有哪些内容没有讲到呢?

今天重点研究如何使用 Statspack 采集执行计划。如果你翻阅 Oracle 官方文档,

很容易误以为 Statspack 在 10.1.0.1 版本后就被 AWR 报表取代、不再提供(AWR 需要额外付费授权,而 Statspack 免费)。

但 Statspack 在 Oracle 11.2.0.1 中依然可用,而且相比早期版本还有增强。

当 Statspack 快照级别为 6 或更高时,就会采集执行计划 —— 不一定能捕获所有 SQL 的执行计划(可以调整采集过滤条件),

默认配置下也能捕获相当多 SQL 的计划。

本文会复用上篇文章里创建的测试表,读取 Statspack 采集保存的执行计划。

我们需要打开两个 SQL*Plus 会话:

第一个以 PERFSTAT 用户(Statspack 数据的属主)登录;

第二个登录为上一篇文章里测试表的属主。

首先我们先看看如何安装 Statspack?

cd $ORACLE_HOME/rdbms/admin目录下。找到如下脚本。

1. spcreate.sql脚本,安装 Statspack,创建 PERFSTAT 用户、表、包(SYS 执行)Oracle

2. spauto.sql脚本,定时快照 Job 脚本,用 DBMS_JOB 定时自动采集 snapshot(文章里面 5 分钟快照就是改这个)

3. spreport.sql脚本,生成 Statspack 性能报告(两个快照之间)

4. sprepsql.sql脚本,单独生成某个 SQL 的 Statspack 明细报告(看 Statspack 里保存的执行计划!你当前系列文章重点)

5. sppurge.sql脚本,清理旧的 Statspack 快照数据

6. spdrop.sql脚本,卸载 Statspack,删除 PERFSTAT 整个方案

7. spdoc.txt脚本, Statspack 官方说明文档,必读

安装完毕后,使用方法

1. sysdba执行spcreate.sql安装,创建PERFSTAT用户。

2. 切换到perfstat用户

3. 执行spauto.sql创建定时任务(或者自己写自定义定时快照脚本,搭配 DBMS_LOCK.SLEEP这种,复现测试)

4. 快照采集完之后,执行spreport.sql执行sprepsql.sql查看报告和SQL 执行计划

开始我们的实验,使用PERFSTAT 用户会执行下面的脚本,每 5 分钟采集一次级别 7 的 Statspack 快照。

#BEGIN
#  STATSPACK.SNAP(i_snap_level=>7);
#  DBMS_LOCK.SLEEP(300);
#  STATSPACK.SNAP(i_snap_level=>7);
#  DBMS_LOCK.SLEEP(300);
#  STATSPACK.SNAP(i_snap_level=>7);
#  DBMS_LOCK.SLEEP(300);
#  STATSPACK.SNAP(i_snap_level=>7);
#END;
#/

在 PERFSTAT 用户运行上述脚本的同时,另一个会话会多次执行下面这段脚本(每次 Statspack 采集周期内至少执行 2 次):

#SPOOL BindTestPlans.txt
#
#SET AUTOTRACE OFF
#ALTER SESSION SET STATISTICS_LEVEL='ALL';
#
#ALTER SESSION SET OPTIMIZER_MODE='ALL_ROWS';
#ALTER SYSTEM FLUSH SHARED_POOL;
#
#VARIABLE N1 NUMBER
#VARIABLE N2 NUMBER
#EXEC :N1:=1
#EXEC :N2:=1
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=1000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=10000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#ALTER SESSION SET OPTIMIZER_MODE='FIRST_ROWS_1';
#VARIABLE N1 NUMBER
#VARIABLE N2 NUMBER
#EXEC :N1:=1
#EXEC :N2:=1
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=1000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=10000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#ALTER SESSION SET OPTIMIZER_MODE='FIRST_ROWS_10';
#VARIABLE N1 NUMBER
#VARIABLE N2 NUMBER
#EXEC :N1:=1
#EXEC :N2:=1
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=1000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=10000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#ALTER SESSION SET OPTIMIZER_MODE='FIRST_ROWS_1000';
#VARIABLE N1 NUMBER
#VARIABLE N2 NUMBER
#EXEC :N1:=1
#EXEC :N2:=1
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=1000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=10000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#EXEC :N2:=100000
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  T3.C1,
#  SUBSTR(T1.C2,1,10) T1_C2,
#  SUBSTR(T2.C2,1,10) T2_C2
#FROM
#  T3,
#  T2,
#  T1
#WHERE
#  T1.C1=T3.C1
#  AND T1.C1=T2.C1
#  AND T1.C1 BETWEEN :N1 AND :N2;
#
#SELECT
#  *
#FROM
#  TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
#
#SPOOL OFF

上面这个脚本会切换优化器模式,并使用不同的绑定变量值执行同一条 SQL 语句。采集若干个 Statspack 快照之后,

我们就可以用如下 SQL,查看快照里是否存在同一条 SQL 拥有多个不同执行计划的情况

(注意:最好指定一个 Statspack 快照区间,而不是查询全部快照)。

#SPOOL MultiplePlans.txt
#
#SELECT
#  SQL_ID,
#  COUNT(DISTINCT PLAN_HASH_VALUE) C
#FROM
#  PERFSTAT.STATS$SQL_PLAN_USAGE
#GROUP BY
#  SQL_ID
#HAVING
#  COUNT(DISTINCT PLAN_HASH_VALUE)>1;
#
#SPOOL OFF

sql的执行结构如下:

SQL_ID                 C
------------- ----------
asc81p5ttbyf4          2
94bv1jwkzcc38          2
77z8bh7b87r1s          4
ga9j9xk5cy9s0          2
ddnbt67ftu9ds          2
0fr8zhn4ymu3v          2
cvn54b7yz0s8u          2
gjm43un5cy843          2
ff9zaqp3qfnah          2
gx4mv66pvj3xz          2
cvq22z77c8fww          3
a13qjgdbjcurr          2
1gu8t96d0bdmu          2
2x7j98pyk8ggm          2
8p3pacrbngv80          2
c6awqs517jpj0          2
cds8ys5zwkrpk          2
0u02w6ryqkg66          2
39m4sx9k63ba2          2
7ng34ruy5awxq          4
9dq71tc7vasgu          2
53saa2zkr6wc3          2
bsa0wjtftg3uw          2
cn5wth3738x0x          2
f3g84j69n0tjh          2
9nv4n7b54ph9a          2
0g5sb3zpqzss8          2

有意思:这里有几条 SQL,其中两条各存在 2 种执行计划、一条存在 3 种执行计划,还有两条各有 4 种执行计划。我们刚才的 SQL 没有限定只查询某个 Statspack 快照时间段,所以其中部分执行计划可能是很早之前采集的。我们来看其中一条 SQL 对应的执行计划

(注意:Statspack 快照不会采集谓词信息段和备注段,因此下面展示的执行计划会剔除这两部分内容)。

#SET LINESIZE 150
#SET PAGESIZE 10000
#SPOOL StatspackPlan.txt
#
#SELECT /*+ ORDERED */
#  T.*
#FROM
#  (SELECT DISTINCT
#    PLAN_HASH_VALUE
#  FROM
#    PERFSTAT.STATS$SQL_PLAN_USAGE
#  WHERE
#    SQL_ID='7ng34ruy5awxq'
#  ORDER BY
#    PLAN_HASH_VALUE) SPU,
#  TABLE(DBMS_XPLAN.DISPLAY(
#    'PERFSTAT.STATS$SQL_PLAN',
#    NULL,
#    'TYPICAL -PREDICATE -NOTE',
#    'PLAN_HASH_VALUE='||SPU.PLAN_HASH_VALUE)) T;
#
#SPOOL OFF

执行sql后,执行结果如下:

#------------------------------------------------------------
#| Id  | Operation                      | Name              |
#------------------------------------------------------------
#|   0 | SELECT STATEMENT               |                   |
#|   1 |  MERGE JOIN OUTER              |                   |
#|   2 |   SORT JOIN                    |                   |
#|   3 |    NESTED LOOPS OUTER          |                   |
#|   4 |     TABLE ACCESS CLUSTER       | IND$              |
#|   5 |      INDEX UNIQUE SCAN         | I_OBJ#            |
#|   6 |     TABLE ACCESS BY INDEX ROWID| IND_STATS$        |
#|   7 |      INDEX UNIQUE SCAN         | I_IND_STATS$_OBJ# |
#|   8 |   SORT JOIN                    |                   |
#|   9 |    VIEW                        |                   |
#|  10 |     SORT GROUP BY              |                   |
#|  11 |      TABLE ACCESS CLUSTER      | CDEF$             |
#|  12 |       INDEX UNIQUE SCAN        | I_COBJ#           |
#------------------------------------------------------------
#
#----------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
#----------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |                   |       |       |     7 (100)|          |
#|   1 |  SORT ORDER BY                 |                   |     2 |   374 |     7  (43)| 00:00:01 |
#|   2 |   HASH JOIN OUTER              |                   |     2 |   374 |     6  (34)| 00:00:01 |
#|   3 |    NESTED LOOPS OUTER          |                   |     2 |   288 |     2   (0)| 00:00:01 |
#|   4 |     TABLE ACCESS CLUSTER       | IND$              |     2 |   184 |     2   (0)| 00:00:01 |
#|   5 |      INDEX UNIQUE SCAN         | I_OBJ#            |     1 |       |     1   (0)| 00:00:01 |
#|   6 |     TABLE ACCESS BY INDEX ROWID| IND_STATS$        |     1 |    52 |     0   (0)|          |
#|   7 |      INDEX UNIQUE SCAN         | I_IND_STATS$_OBJ# |     1 |       |     0   (0)|          |
#|   8 |    VIEW                        |                   |     1 |    43 |     3  (34)| 00:00:01 |
#|   9 |     SORT GROUP BY              |                   |     1 |    15 |     3  (34)| 00:00:01 |
#|  10 |      TABLE ACCESS CLUSTER      | CDEF$             |     1 |    15 |     2   (0)| 00:00:01 |
#|  11 |       INDEX UNIQUE SCAN        | I_COBJ#           |     1 |       |     1   (0)| 00:00:01 |
#----------------------------------------------------------------------------------------------------
#
#----------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
#----------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |                   |       |       |     5 (100)|          |
#|   1 |  SORT GROUP BY                 |                   |     2 |   342 |     5  (20)| 00:00:01 |
#|   2 |   NESTED LOOPS OUTER           |                   |     2 |   342 |     4   (0)| 00:00:01 |
#|   3 |    NESTED LOOPS OUTER          |                   |     2 |   312 |     2   (0)| 00:00:01 |
#|   4 |     TABLE ACCESS CLUSTER       | IND$              |     2 |   184 |     2   (0)| 00:00:01 |
#|   5 |      INDEX UNIQUE SCAN         | I_OBJ#            |     1 |       |     1   (0)| 00:00:01 |
#|   6 |     TABLE ACCESS BY INDEX ROWID| IND_STATS$        |     1 |    64 |     0   (0)|          |
#|   7 |      INDEX UNIQUE SCAN         | I_IND_STATS$_OBJ# |     1 |       |     0   (0)|          |
#|   8 |    TABLE ACCESS CLUSTER        | CDEF$             |     1 |    15 |     1   (0)| 00:00:01 |
#|   9 |     INDEX UNIQUE SCAN          | I_COBJ#           |     1 |       |     0   (0)|          |
#----------------------------------------------------------------------------------------------------
#
#-----------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
#-----------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |                   |       |       |     7 (100)|          |
#|   1 |  SORT ORDER BY                  |                   |     2 |   374 |     7  (43)| 00:00:01 |
#|   2 |   HASH JOIN OUTER               |                   |     2 |   374 |     6  (34)| 00:00:01 |
#|   3 |    NESTED LOOPS OUTER           |                   |     2 |   288 |     2   (0)| 00:00:01 |
#|   4 |     TABLE ACCESS CLUSTER        | IND$              |     2 |   184 |     2   (0)| 00:00:01 |
#|   5 |      INDEX UNIQUE SCAN          | I_OBJ#            |     1 |       |     1   (0)| 00:00:01 |
#|   6 |     TABLE ACCESS BY INDEX ROWID | IND_STATS$        |     1 |    52 |     0   (0)|          |
#|   7 |      INDEX UNIQUE SCAN          | I_IND_STATS$_OBJ# |     1 |       |     0   (0)|          |
#|   8 |    VIEW                         |                   |     1 |    43 |     3  (34)| 00:00:01 |
#|   9 |     SORT GROUP BY               |                   |     1 |    15 |     3  (34)| 00:00:01 |
#|  10 |      TABLE ACCESS BY INDEX ROWID| CDEF$             |     1 |    15 |     2   (0)| 00:00:01 |
#|  11 |       INDEX RANGE SCAN          | I_CDEF2           |     4 |       |     1   (0)| 00:00:01 |
#-----------------------------------------------------------------------------------------------------

好吧,这并不是我们刚才执行的那条 SQL 的执行计划。

但有意思的是,Oracle 的一条内部 SQL 居然生成了 4 种不同的执行计划

(其中一个计划看起来是在 RULE 优化器模式下生成的,依据就是**缺少 Cost(成本)列**)。

我们重新查询(说明:目标 SQL_ID 本来会在 DBMS_XPLAN 的输出中展示,但这里假设我们不知道这个 SQL_ID,也不想去查询 V$SQLAREA或V$SQL 视图):

#SET LINESIZE 150
#SET PAGESIZE 10000
#SPOOL StatspackPlan.txt
#
#SELECT /*+ ORDERED */
#  T.*
#FROM
#  (SELECT DISTINCT
#    PLAN_HASH_VALUE
#  FROM
#    PERFSTAT.STATS$SQL_PLAN_USAGE
#  WHERE
#    SQL_ID='77z8bh7b87r1s'
#  ORDER BY
#    PLAN_HASH_VALUE) SPU,
#  TABLE(DBMS_XPLAN.DISPLAY(
#    'PERFSTAT.STATS$SQL_PLAN',
#    NULL,
#    'TYPICAL -PREDICATE -NOTE',
#    'PLAN_HASH_VALUE='||SPU.PLAN_HASH_VALUE)) T;
#
#SPOOL OFF

输入结果如下:

#-----------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
#-----------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |              |       |       |  1257 (100)|          |
#|   1 |  FILTER                        |              |       |       |            |          |
#|   2 |   HASH JOIN                    |              |    13 |  8762 |  1257   (1)| 00:00:16 |
#|   3 |    TABLE ACCESS BY INDEX ROWID | T2           |  1000 |   138K|     4   (0)| 00:00:01 |
#|   4 |     INDEX RANGE SCAN           | SYS_C0017308 |  1000 |       |     3   (0)| 00:00:01 |
#|   5 |    NESTED LOOPS                |              |       |       |            |          |
#|   6 |     NESTED LOOPS               |              |    13 |  3458 |  1253   (1)| 00:00:16 |
#|   7 |      TABLE ACCESS FULL         | T3           |  1000 |  5000 |  1227   (1)| 00:00:15 |
#|   8 |      INDEX UNIQUE SCAN         | SYS_C0017307 |     1 |       |     1   (0)| 00:00:01 |
#|   9 |     TABLE ACCESS BY INDEX ROWID| T1           |     1 |   261 |     2   (0)| 00:00:01 |
#-----------------------------------------------------------------------------------------------
#
#--------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
#--------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |       |       |       | 15215 (100)|          |
#|   1 |  FILTER                         |              |       |       |       |            |          |
#|   2 |   HASH JOIN                     |              | 32260 |    12M|       | 15215   (1)| 00:03:03 |
#|   3 |    TABLE ACCESS FULL            | T3           |   100K|   488K|       | 10214   (1)| 00:02:03 |
#|   4 |    MERGE JOIN                   |              | 32260 |    12M|       |  4999   (1)| 00:01:00 |
#|   5 |     TABLE ACCESS BY INDEX ROWID | T1           |   100K|    24M|       |  3897   (1)| 00:00:47 |
#|   6 |      INDEX RANGE SCAN           | SYS_C0017307 |   100K|       |       |   191   (1)| 00:00:03 |
#|   7 |     SORT JOIN                   |              | 32260 |  4473K|  9752K|  1103   (1)| 00:00:14 |
#|   8 |      TABLE ACCESS BY INDEX ROWID| T2           | 32260 |  4473K|       |    80   (0)| 00:00:01 |
#|   9 |       INDEX RANGE SCAN          | SYS_C0017308 | 32260 |       |       |    56   (0)| 00:00:01 |
#--------------------------------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
#------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |       |       | 10217 (100)|          |
#|   1 |  FILTER                         |              |       |       |            |          |
#|   2 |   NESTED LOOPS                  |              |       |       |            |          |
#|   3 |    NESTED LOOPS                 |              |    12 |  4896 | 10217   (1)| 00:02:03 |
#|   4 |     NESTED LOOPS                |              |    12 |  3192 | 10216   (1)| 00:02:03 |
#|   5 |      TABLE ACCESS FULL          | T3           |   100K|   488K| 10214   (1)| 00:02:03 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |     1 |   261 |     2   (0)| 00:00:01 |
#|   7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |     1 |       |     1   (0)| 00:00:01 |
#|   8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |     1 |       |     0   (0)|          |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |     1 |   142 |     1   (0)| 00:00:01 |
#------------------------------------------------------------------------------------------------
#
#-------------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name         | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |
#-------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |              |       |       |       | 10897 (100)|          |
#|   1 |  FILTER                        |              |       |       |       |            |          |
#|   2 |   HASH JOIN                    |              |  9998 |  3983K|       | 10897   (1)| 00:02:11 |
#|   3 |    TABLE ACCESS FULL           | T3           | 10000 | 50000 |       | 10214   (1)| 00:02:03 |
#|   4 |    HASH JOIN                   |              |  9999 |  3935K|  2432K|   682   (1)| 00:00:09 |
#|   5 |     TABLE ACCESS BY INDEX ROWID| T2           | 16130 |  2236K|       |    41   (0)| 00:00:01 |
#|   6 |      INDEX RANGE SCAN          | SYS_C0017308 | 16130 |       |       |    29   (0)| 00:00:01 |
#|   7 |     TABLE ACCESS BY INDEX ROWID| T1           | 10000 |  2548K|       |   392   (0)| 00:00:05 |
#|   8 |      INDEX RANGE SCAN          | SYS_C0017307 | 10000 |       |       |    21   (0)| 00:00:01 |
#-------------------------------------------------------------------------------------------------------

这看起来就是我们这条查询对应的执行计划了,但这条查询真的只有 4 种不同的执行计划吗(按理说自适应游标共享 ACS 应该已经生效)?

实际上,数据库创建了超过 4 个子游标,但**去重之后只有 4 套不一样的执行计划**,这点很有意思。

上面这几组计划(从上往下看)的连接方式分别是:

嵌套循环(一张表和另一张表的索引之间)、嵌套循环、哈希连接

排序合并连接、哈希连接

嵌套循环、嵌套循环、嵌套循环

哈希连接、哈希连接

Nested Loops (between a table and an index for another table), Nested Loops, Hash Join

Sort – Merge Join, Hash Join

Nested Loops, Nested Loops, Nested Loops

Hash Join, Hash Join

基于成本的优化器(CBO)确实很巧妙。

Statspack 能够采集到执行计划固然很棒,但因为缺少谓词信息,计划的参考价值会打折扣。

接下来我们看脚本运行期间抓取到的 DBMS_XPLAN 输出,只在生成新执行计划(或者新子游标)的时候才打印计划:

#SQL_ID  77z8bh7b87r1s, child number 0                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |      1 |00:00:00.08 |   37173 |
#|*  1 |  FILTER                         |              |      1 |        |      1 |00:00:00.08 |   37173 |
#|   2 |   NESTED LOOPS                  |              |      1 |        |      1 |00:00:00.08 |   37173 |
#|   3 |    NESTED LOOPS                 |              |      1 |      1 |      1 |00:00:00.08 |   37172 |
#|   4 |     NESTED LOOPS                |              |      1 |      1 |      1 |00:00:00.08 |   37169 |
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |      1 |      1 |00:00:00.08 |   37165 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |      1 |      1 |      1 |00:00:00.01 |       4 |
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |      1 |      1 |      1 |00:00:00.01 |       3 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |      1 |      1 |      1 |00:00:00.01 |       3 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |      1 |      1 |      1 |00:00:00.01 |       1 |
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 1                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 2222254696                                  
#
#------------------------------------------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
#------------------------------------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |              |      1 |        |   1000 |00:00:00.08 |   37382 |       |       |          |
#|*  1 |  FILTER                        |              |      1 |        |   1000 |00:00:00.08 |   37382 |       |       |          |
#|*  2 |   HASH JOIN                    |              |      1 |    998 |   1000 |00:00:00.08 |   37382 |  1452K|  1452K| 1476K (0)|
#|*  3 |    TABLE ACCESS FULL           | T3           |      1 |   1000 |   1000 |00:00:00.07 |   37164 |       |       |          |
#|*  4 |    HASH JOIN                   |              |      1 |    999 |   1000 |00:00:00.01 |     218 |   830K|   830K| 1277K (0)|
#|   5 |     TABLE ACCESS BY INDEX ROWID| T2           |      1 |   1000 |   1000 |00:00:00.01 |      42 |       |       |          |
#|*  6 |      INDEX RANGE SCAN          | SYS_C0017308 |      1 |   1000 |   1000 |00:00:00.01 |       4 |       |       |          |
#|   7 |     TABLE ACCESS BY INDEX ROWID| T1           |      1 |   1000 |   1000 |00:00:00.01 |     176 |       |       |          |
#|*  8 |      INDEX RANGE SCAN          | SYS_C0017307 |      1 |   1000 |   1000 |00:00:00.01 |      71 |       |       |          |
#------------------------------------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)  
#   2 - access("T1"."C1"="T3"."C1")         
#   3 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   4 - access("T1"."C1"="T2"."C1")         
#   6 - access("T2"."C1">=:N1 AND "T2"."C1"<=:N2)             
#   8 - access("T1"."C1">=:N1 AND "T1"."C1"<=:N2)             
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 2      
#-------------------------------------      
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                
#BETWEEN :N1 AND :N2      
#
#Plan hash value: 2222254696                                  
#
#------------------------------------------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
#------------------------------------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |              |      1 |        |  10000 |00:00:00.14 |   39279 |       |       |          |
#|*  1 |  FILTER                        |              |      1 |        |  10000 |00:00:00.14 |   39279 |       |       |          |
#|*  2 |   HASH JOIN                    |              |      1 |   9998 |  10000 |00:00:00.14 |   39279 |  1452K|  1452K| 1795K (0)|
#|*  3 |    TABLE ACCESS FULL           | T3           |      1 |  10000 |  10000 |00:00:00.08 |   37164 |       |       |          |
#|*  4 |    HASH JOIN                   |              |      1 |   9999 |  10000 |00:00:00.04 |    2115 |  3436K|   948K| 3949K (0)|
#|   5 |     TABLE ACCESS BY INDEX ROWID| T2           |      1 |  16130 |  10000 |00:00:00.01 |     391 |       |       |          |
#|*  6 |      INDEX RANGE SCAN          | SYS_C0017308 |      1 |  16130 |  10000 |00:00:00.01 |      20 |       |       |          |
#|   7 |     TABLE ACCESS BY INDEX ROWID| T1           |      1 |  10000 |  10000 |00:00:00.01 |    1724 |       |       |          |
#|*  8 |      INDEX RANGE SCAN          | SYS_C0017307 |      1 |  10000 |  10000 |00:00:00.01 |     686 |       |       |          |
#------------------------------------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)  
#   2 - access("T1"."C1"="T3"."C1")         
#   3 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   4 - access("T1"."C1"="T2"."C1")         
#   6 - access("T2"."C1">=:N1 AND "T2"."C1"<=:N2)             
#   8 - access("T1"."C1">=:N1 AND "T1"."C1"<=:N2)             
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 3      
#-------------------------------------      
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                
#BETWEEN :N1 AND :N2      
#
#Plan hash value: 736968136                 
#
#-------------------------------------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
#-------------------------------------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |    100K|00:00:01.02 |   58272 |       |       |          |
#|*  1 |  FILTER                         |              |      1 |        |    100K|00:00:01.02 |   58272 |       |       |          |
#|*  2 |   HASH JOIN                     |              |      1 |  32260 |    100K|00:00:00.97 |   58272 |  3838K|  1862K| 5510K (0)|
#|*  3 |    TABLE ACCESS FULL            | T3           |      1 |    100K|    100K|00:00:00.09 |   37164 |       |       |          |
#|   4 |    MERGE JOIN                   |              |      1 |  32260 |    100K|00:00:00.68 |   21108 |       |       |          |
#|   5 |     TABLE ACCESS BY INDEX ROWID | T1           |      1 |    100K|    100K|00:00:00.22 |   17215 |       |       |          |
#|*  6 |      INDEX RANGE SCAN           | SYS_C0017307 |      1 |    100K|    100K|00:00:00.06 |    6844 |       |       |          |
#|*  7 |     SORT JOIN                   |              |    100K|  32260 |    100K|00:00:00.29 |    3893 |    30M|  1975K|   26M (0)|
#|   8 |      TABLE ACCESS BY INDEX ROWID| T2           |      1 |  32260 |    100K|00:00:00.06 |    3893 |       |       |          |
#|*  9 |       INDEX RANGE SCAN          | SYS_C0017308 |      1 |  32260 |    100K|00:00:00.02 |     189 |       |       |          |
#-------------------------------------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   2 - access("T1"."C1"="T3"."C1")                           
#   3 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   6 - access("T1"."C1">=:N1 AND "T1"."C1"<=:N2)             
#   7 - access("T1"."C1"="T2"."C1")                           
#       filter("T1"."C1"="T2"."C1")                           
#   9 - access("T2"."C1">=:N1 AND "T2"."C1"<=:N2)             
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 4                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                                  
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |    100 |00:00:00.07 |   37411 |
#|*  1 |  FILTER                         |              |      1 |        |    100 |00:00:00.07 |   37411 |
#|   2 |   NESTED LOOPS                  |              |      1 |        |    100 |00:00:00.07 |   37411 |
#|   3 |    NESTED LOOPS                 |              |      1 |      1 |    100 |00:00:00.07 |   37311 |
#|   4 |     NESTED LOOPS                |              |      1 |      1 |    100 |00:00:00.07 |   37291 |
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |      1 |    100 |00:00:00.07 |   37171 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |    100 |      1 |    100 |00:00:00.01 |     120 |
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |    100 |      1 |    100 |00:00:00.01 |      20 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |    100 |      1 |    100 |00:00:00.01 |      20 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |    100 |      1 |    100 |00:00:00.01 |     100 |
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 5                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                                  
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |   1000 |00:00:00.08 |   39469 |
#|*  1 |  FILTER                         |              |      1 |        |   1000 |00:00:00.08 |   39469 |
#|   2 |   NESTED LOOPS                  |              |      1 |        |   1000 |00:00:00.08 |   39469 |
#|   3 |    NESTED LOOPS                 |              |      1 |      4 |   1000 |00:00:00.08 |   38469 |
#|   4 |     NESTED LOOPS                |              |      1 |      4 |   1000 |00:00:00.08 |   38350 |
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |   1000 |   1000 |00:00:00.08 |   37231 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |   1000 |      1 |   1000 |00:00:00.01 |    1119 |
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |   1000 |      1 |   1000 |00:00:00.01 |     119 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |   1000 |      1 |   1000 |00:00:00.01 |     119 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |   1000 |      1 |   1000 |00:00:00.01 |    1000 |
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 6                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                                  
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |  10000 |00:00:00.21 |   63553 |
#|*  1 |  FILTER                         |              |      1 |        |  10000 |00:00:00.21 |   63553 |
#|   2 |   NESTED LOOPS                  |              |      1 |        |  10000 |00:00:00.20 |   63553 |
#|   3 |    NESTED LOOPS                 |              |      1 |      3 |  10000 |00:00:00.17 |   53553 |
#|   4 |     NESTED LOOPS                |              |      1 |      3 |  10000 |00:00:00.14 |   50692 |
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |   6668 |  10000 |00:00:00.09 |   37831 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |  10000 |      1 |  10000 |00:00:00.04 |   12861 |
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |  10000 |      1 |  10000 |00:00:00.02 |    2861 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |  10000 |      1 |  10000 |00:00:00.02 |    2861 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |  10000 |      1 |  10000 |00:00:00.02 |   10000 |
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 7                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                                  
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |    100K|00:00:01.45 |     316K|
#|*  1 |  FILTER                         |              |      1 |        |    100K|00:00:01.45 |     316K|
#|   2 |   NESTED LOOPS                  |              |      1 |        |    100K|00:00:01.39 |     316K|
#|   3 |    NESTED LOOPS                 |              |      1 |      3 |    100K|00:00:01.07 |     216K|
#|   4 |     NESTED LOOPS                |              |      1 |      9 |    100K|00:00:00.76 |     180K|
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |    100K|    100K|00:00:00.16 |   43822 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |    100K|      1 |    100K|00:00:00.46 |     136K|
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |    100K|      1 |    100K|00:00:00.20 |   36565 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |    100K|      1 |    100K|00:00:00.17 |   36565 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |    100K|      1 |    100K|00:00:00.18 |     100K|
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 8                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 1056058413                                  
#
#----------------------------------------------------------------------------------------------------------
#| Id  | Operation                       | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
#----------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT                |              |      1 |        |      1 |00:00:00.07 |   37173 |
#|*  1 |  FILTER                         |              |      1 |        |      1 |00:00:00.07 |   37173 |
#|   2 |   NESTED LOOPS                  |              |      1 |        |      1 |00:00:00.07 |   37173 |
#|   3 |    NESTED LOOPS                 |              |      1 |      1 |      1 |00:00:00.07 |   37172 |
#|   4 |     NESTED LOOPS                |              |      1 |      1 |      1 |00:00:00.07 |   37169 |
#|*  5 |      TABLE ACCESS FULL          | T3           |      1 |      1 |      1 |00:00:00.07 |   37165 |
#|   6 |      TABLE ACCESS BY INDEX ROWID| T1           |      1 |      1 |      1 |00:00:00.01 |       4 |
#|*  7 |       INDEX UNIQUE SCAN         | SYS_C0017307 |      1 |      1 |      1 |00:00:00.01 |       3 |
#|*  8 |     INDEX UNIQUE SCAN           | SYS_C0017308 |      1 |      1 |      1 |00:00:00.01 |       3 |
#|   9 |    TABLE ACCESS BY INDEX ROWID  | T2           |      1 |      1 |      1 |00:00:00.01 |       1 |
#----------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   5 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   7 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#   8 - access("T1"."C1"="T2"."C1")                           
#       filter(("T2"."C1">=:N1 AND "T2"."C1"<=:N2))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)
#
#-
#
#SQL_ID  77z8bh7b87r1s, child number 9                        
#-------------------------------------                        
#SELECT   T3.C1,   SUBSTR(T1.C2,1,10) T1_C2,   SUBSTR(T2.C2,1,10) T2_C2                                   
#FROM   T3,   T2,   T1 WHERE   T1.C1=T3.C1   AND T1.C1=T2.C1   AND T1.C1                                  
#BETWEEN :N1 AND :N2                                          
#
#Plan hash value: 300618627                                   
#
#------------------------------------------------------------------------------------------------------------------------------------
#| Id  | Operation                      | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
#------------------------------------------------------------------------------------------------------------------------------------
#|   0 | SELECT STATEMENT               |              |      1 |        |    100 |00:00:00.07 |   37298 |       |       |          |
#|*  1 |  FILTER                        |              |      1 |        |    100 |00:00:00.07 |   37298 |       |       |          |
#|*  2 |   HASH JOIN                    |              |      1 |     13 |    100 |00:00:00.07 |   37298 |   711K|   711K| 1272K (0)|
#|   3 |    TABLE ACCESS BY INDEX ROWID | T2           |      1 |    100 |    100 |00:00:00.01 |       7 |       |       |          |
#|*  4 |     INDEX RANGE SCAN           | SYS_C0017308 |      1 |    100 |    100 |00:00:00.01 |       3 |       |       |          |
#|   5 |    NESTED LOOPS                |              |      1 |        |    100 |00:00:00.07 |   37291 |       |       |          |
#|   6 |     NESTED LOOPS               |              |      1 |     13 |    100 |00:00:00.07 |   37191 |       |       |          |
#|*  7 |      TABLE ACCESS FULL         | T3           |      1 |    100 |    100 |00:00:00.07 |   37171 |       |       |          |
#|*  8 |      INDEX UNIQUE SCAN         | SYS_C0017307 |    100 |      1 |    100 |00:00:00.01 |      20 |       |       |          |
#|   9 |     TABLE ACCESS BY INDEX ROWID| T1           |    100 |      1 |    100 |00:00:00.01 |     100 |       |       |          |
#------------------------------------------------------------------------------------------------------------------------------------
#
#Predicate Information (identified by operation id):          
#---------------------------------------------------          
#   1 - filter(:N1<=:N2)                                      
#   2 - access("T1"."C1"="T2"."C1")                           
#   4 - access("T2"."C1">=:N1 AND "T2"."C1"<=:N2)             
#   7 - filter(("T3"."C1"<=:N2 AND "T3"."C1">=:N1))           
#   8 - access("T1"."C1"="T3"."C1")                           
#       filter(("T1"."C1"<=:N2 AND "T1"."C1">=:N1))           
#
#Note             
#-----            
#   - dynamic sampling used for this statement (level=2)

注意看【备注】部分,里面说明执行了**2 级动态采样**,但并没有标注该采样仅针对 T2 表(原因:T2 表当时没有收集统计信息)。


我们可以去查看这个 SQL_ID 对应的 `V$SQL_SHARED_CURSOR` 视图,会很有收获。

该视图中的字段记录了创建子游标的原因。下面是执行 `DESC V$SQL_SHARED_CURSOR` 得到的字段列表:

Name                         
 ------------------------------
 UNBOUND_CURSOR               
 SQL_TYPE_MISMATCH            
 OPTIMIZER_MISMATCH           
 OUTLINE_MISMATCH             
 STATS_ROW_MISMATCH           
 LITERAL_MISMATCH             
 FORCE_HARD_PARSE             
 EXPLAIN_PLAN_CURSOR          
 BUFFERED_DML_MISMATCH        
 PDML_ENV_MISMATCH            
 INST_DRTLD_MISMATCH          
 SLAVE_QC_MISMATCH            
 TYPECHECK_MISMATCH           
 AUTH_CHECK_MISMATCH          
 BIND_MISMATCH                
 DESCRIBE_MISMATCH            
 LANGUAGE_MISMATCH            
 TRANSLATION_MISMATCH         
 BIND_EQUIV_FAILURE           
 INSUFF_PRIVS                 
 INSUFF_PRIVS_REM             
 REMOTE_TRANS_MISMATCH        
 LOGMINER_SESSION_MISMATCH    
 INCOMP_LTRL_MISMATCH         
 OVERLAP_TIME_MISMATCH        
 EDITION_MISMATCH             
 MV_QUERY_GEN_MISMATCH        
 USER_BIND_PEEK_MISMATCH      
 TYPCEHEK_DEP_MISMATCH          
 NO_TRIGGER_MISMATCH          
 FLASHBACK_CURSOR             
 ANYDATA_TRANSFORMATION       
 INCOMPLETE_CURSOR            
 TOP_LEVEL_RPI_CURSOR         
 DIFFERENT_LONG_LENGTH        
 LOGICAL_STANDBY_APPLY        
 DIFF_CALL_DURN               
 BIND_UACS_DIFF               
 PLSQL_CMP_SWITCHS_DIFF       
 CURSOR_PARTS_MISMATCH        
 STB_OBJECT_MISMATCH          
 CROSSEDITION_TRIGGER_MISMATCH
 PQ_SLAVE_MISMATCH            
 TOP_LEVEL_DDL_MISMATCH       
 MULTI_PX_MISMATCH            
 BIND_PEEKED_PQ_MISMATCH      
 MV_REWRITE_MISMATCH          
 ROLL_INVALID_MISMATCH        
 OPTIMIZER_MODE_MISMATCH      
 PX_MISMATCH                  
 MV_STALEOBJ_MISMATCH         
 FLASHBACK_TABLE_MISMATCH     
 LITREP_COMP_MISMATCH         
 PLSQL_DEBUG                  
 LOAD_OPTIMIZER_STATS         
 ACL_MISMATCH                 
 FLASHBACK_ARCHIVE_MISMATCH   
 LOCK_USER_SCHEMA_FAILED      
 REMOTE_MAPPING_MISMATCH      
 LOAD_RUNTIME_HEAP_FAILED     
 HASH_MATCH_FAILED            
 PURGED_CURSOR                
 BIND_LENGTH_UPGRADEABLE

Oracle Database 11.2.0.1 确实内置了非常多会触发新建子游标的条件。那么,

 在我们这个测试里,生成这些子游标的原因是什么呢(至少是脚本多次执行后,还保留在库缓存中的那些子游标)?

CN USOOSLFEBPISTABDLTBIIRLIOEMUTNFAITDLDBPCSCPTMBMROPMFLPLAFLRLHPB
-- ---------------------------------------------------------------
 0 NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNYNNNNNNNN
 1 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 2 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 3 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 4 NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNYNNNNNYNNNNNNNN
 5 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 6 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 7 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 8 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 9 NNNNNNNNNNNNNNNNNNYNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN

从上面结果可以看出,产生子游标的原因是:**L(LOAD_OPTIMIZER_STATS,加载优化器统计信息)**、**B(BIND_EQUIV_FAILURE,绑定变量等价性校验失败)**、**O(OPTIMIZER_MODE_MISMATCH,优化器模式不匹配)**。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3187021/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 没有了~
请登录后发表评论 登录
全部评论
【DBAplus社群】联合发起人。ACOUG核心成员,Oracle用户组年轻专家。熟悉Oracle的体系结构,擅长Oracle数据库架构规划、SQL优化、OWI方面性能的优化。曾服务于航天、航空、机车、大型制造行业数据库的维护以及系统开发工作,开发过基于Oracle数据库的大型ERP系统。
  • 博文量
    344
  • 访问量
    2473393