1、什么是执行计划
为了执行sql语句,Oracle在内部必须实现许多步骤,这些步骤可能是从数据库中物理检索数据行,或者用某种方法来准备数据行等,接着Oracle会按照一定的顺序一次执行这些步骤,最后将其执行结果作为目标sql的最终执行结果返回给用户。Oracle用来执行目标sql语句的这些步骤的组合就被称为执行计划。
 
2、如何查看执行计划
 
2.1、explain plan命令
如果你问习惯于使用pl/sql developer的同学数据库得到一个sql执行计划,他们很可能不假思索的回答,按F5就可以了。实际上pl/sql developer上按了F5后,调用了explain plan命令,将该命令封装到软件中了。
依次执行下面两条命令
SQL> explain plan for select count(*) from emp;
先使用explain plan命令对目标sql做explain,
SQL> select * from table(dbms_xplan.display);
再查看执行计划。
到底explain plan命令做了什么事情?在10G及以上版本,对目标sql执行explain plan命令后,则Oracle就解析目标sql 所产生的执行计划的具体执行步骤写到plan_table$,随后执行的select * from table(dbms_xplan.display);只是从plan_table$中将这些具体执行步骤以格式化的方式显示出来。plan_table$是一个ON COMMIT PRESERVER ROWS的GLOBAL TEMPORARY TABLE。所以这里Oracle可以做到各个session只能看到自己的执行的sql所产生的执行计划,并且各个session往plan_table$写入执行计划的过程互不干扰。
 
2.2、DBMS_XPLAN包
使用DBMS_XPLAN包中方法是Oracle数据库中得到目标SQL的执行计划的第二种方法,针对不同的应用场景,你可以选择四种方法中的一种:
2.2.1方法一、select * from table(DBMS_XPLAN.display);
这需要与explain plan命令配合使用,它用于查看使用explain plan命令后得到的执行计划,上面已介绍过。
 
2.2.2方法二、select * from table(DBMS_XPLAN.display_cursor(null,null,'advanced'));
它用在sqlplus中查看刚刚执行的SQL执行计划,这里针对方法DBMS_XPLAN.display_cursor所传入的第一个和第二个参数的值均为null,第三个参数的值是'advanced',第三个输入参数的值也可以是‘all’,只不过'advanced'后的显示结果比ALL显示更详细些。
 
2.2.3方法三、select * from table(dbma_xplan.display_cursor('sql_id/hash_value',child_cursor_number,'advanced'));它用于查看指定sql的执行计划,这里针对方法所传入的第一个参数的值是指定sql的sql id或者sql hash value,第二个参数的值是要查看的执行计划所在的child cursor number。只要目标sql所对应的child cursor还在library cache中,我们就可以从v$sql中查到目标sql的child cursor的详细信息,包括sql id、sql hash value、chaild cursor number等,
select sql_text,sql_id,hash_value,child_number from v$sql where sql_text like '%%';查询结果找出对应的sql_id和hash value,本质上sql id 和hash value是一回事,他们是可以互相转换的,所以第一个参数两个值都可以用。只要执行计划所在的child cursor还没有被age out出shared pool,就可以用这种方法获取执行计划。
 
2.2.4方法四、select * from table(dbms_xplan.display_awr('sql id'));它用于查看指定sql的所有的历史执行计划,使用2、3能够显示目标sql执行计划的前提条件是该sql的执行计划还在shared pool中,而如果该sql的执行计划已经被age out出shared pool,那么只要该sql的执行计划被Oracle采集到awr repository中,我们就可以使用方法4来查看该sql的所有历史执行计划。
这里需要说明的是,到目前为止,用dbms_xplan.display_awr和之前的dbms_xplan.display_cursor显示的执行计划相比,有一个非常不好的地方,就是用dbms_xplan.display_awr显示执行计划中看不到执行步骤对应的谓词条件,这是非常糟糕的。因为谓词条件对于我们理解执行计划,特别是理解复杂执行计划是不可或缺的。这里的根本原因是Oracle在把执行计划的采样数据从v$sql挪到awr repository的基表wrh$_sql_plan中时没有保留v$sql_plan中记录谓词条件(包括驱动查询条件和过滤查询条件)的列ACCESS_PREDICATES和FILTER_PREDICATES的值,所以不是DBMS_XPLAN.DISPLAY_CURSOR不想显示谓词条件,而是根本就没有谓词条件可供其显示。
 
2.3、autotrace开关
在sqlplus中将autotrace开关打开也能得到目标sql的执行计划,而且除此之外还能得到目标sql在执行时的资源消耗量,即通过设置autotrace开关我们可以额外观察到目标sql执行时所消耗的物理读,逻辑读,产生redo的数量以及排序的数量等。
设置autotrace开发语法如下:
set autotrace OFF|ON|TRACEONLY
[explan]
[statistics]
(1)在sqlplus的当前session中执行命令set autotrace on,可以将autotrace开发完全打开,在这个session中随后执行的所有sql除了显示sql执行结果之外,还会额外显示这个sql对应的执行计划和资源消耗情况。
(2)在sqlplus的当前session执行命令set autotrace off,可以在当前的session中将autotrace开关关闭,在这个session中随后执行的结果只显示执行结果,autotrace开关默认值是OFF。
(3)在sqlplus的当前session中执行命令set autotrace traceonly,可以在当前session中将autotrace开关以不显示sql执行结果的具体内容的方式完全打开。这种方式与st autotrace on的唯一区别就在于,对应traceonly而言,Oracle只会显示sql执行结果的数量,而不会显示直接结果的具体内容。所以适用于那些sql执行结果的具体内容特别长,会连续刷屏的sql,这种情况下我们往往并不关心这些sql的执行结果的具体内容,而只是关心他们的执行计划和资源消耗情况。
(4)在sqlplus的当前session中执行命令set autotrace traceonly explain,可以在挡在session中将autotrace开关以只显示执行技术的方式打开。这种方式与set autotrace traceonly的区别就在于,不会显示目标sql的资源消耗量和执行结果数量,而只显示执行计划。
(5)在sqlplus的当前session中执行命令set autotrace traceonly statistics,可以在当前session中将autotrace开关以只显示sql的资源消耗量的方式打开,这种方式与set autotrace traceonly的唯一区别在于,不显示目标sql的执行计划,而只会显示目标sql执行结果的数量和资源消耗情况。
Oracle有如下简写:
autotrace可以简写成autot
traceonly----trace
explan-------exp
statistics-----stat
按照上述简写规则,如下的写法都是等价的:
SET AUTOTRACE ON==SET AUTOT ON
SET AUTOTRACE OFF ==SET AUTOT OFF
SET AUTOTRACE TRACEONLY ==SET AUTOT TRACE
SET AUTOTRACE TRACEONLY EXPLAIN ==SET AUTOT TRACE EXP
SET AUTOTRACE TRACEONLY STATISTICS ==SET AUTOT TRACE STAT
 
2.4、10046时间和tkprof命令
使用10046事件是在Oracle数据库中查看目标SQL的执行计划的另一种方法,这种方法与使用explain plan命令、DBMS_XPLAN包和AUTOTRACE开关的不同之处在于,所得到的执行计划中明确显示了目标SQL实际执行计划中每一个执行步骤所消耗的逻辑读、物理读和花费的时间。这种细粒度的明显显示在我们诊断复杂SQL的性能问题时尤为有用,而且这也是其他三种方法所不能提供的(实际上,用GATHER_PLAN_STATISTICS Hint配合DBMS_XPLAN包一起使用也可以达到类似10046事件这种细粒度的明细显示效果)。执行10046事件的步骤:
a)首先在当前session中激活10046事件
b)接着在此session中执行目标SQL
c)最后在此session中关闭10046事件
当执行完上述步骤后,Oracle就会将目标SQL的执行计划和明细资源消耗写入此session所对应的trace文件中,查看这个trace文件就能知道目标sql的执行计划和资源消耗明细,Oracle会在参数USER_DUMP_DEST所代表的目录下生产这个trace文件,其命名格式为"实例名_ora_当前session的spid.trc",例如oratest_ora_219.trc。通常可以使用如下这两种方法在当前session中激活10046事件:
在当前session中执行alter session set events '10046 trace name context forever,level 12';
在当前session中执行oradebug event 10046 trace name context forever,level 12
上述命令的关键字level后的数字是表示设置的10046事件的level值,这个值是可以修改的,我们通常使用的值为12,表示在产生的trace文件中除了有目标SQL的执行计划和资源消耗明细之外,还会包含目标SQL所使用的绑定变量的值以及该session所经历的等待事件,除了上述LEVEL值之外,其他部分都是固定的语法。这里我们推荐使用第二种方法,因为可以在激活10046事件后执行命令oradebug tracefile_name来得到当前session所对应的trace文件的具体路径和名称。
对应的,在当前session中关闭10046事件的两种方法为:
在当前session中执行:
alter session set events '10046 trace name context off';
oradebug event 10046 trace name context off;
这里需要注意的是,10046事件所产生的原始trace文件我们习惯称之为裸trace文件(new trace),Oracle记录在裸trace文件中的内容一眼看上去并不是只管,也不是那么容易能看懂,为了让上述裸trace文件能够以一种更直观、更容易懂的方式展现出来,Oracle提供了tkprof命令,这个命令是Oracle自带的,可以用它来翻译上述裸trace文件,从随后的示例中可以看到翻译后的内容确实更直观。
示例:
oradebug setmypid      ----表示对当前session使用oradebug命令
oradebug event 10046 trace name context forever,level 12;     --打开10046事件
select empno from scott.emp;                                                       --目标SQL
oradebug tracefile_name     --显示trace文件路径
oradebug event 10046 trace name context off;                            --关闭10046事件
 
开启另外一个窗口:
tkprof d:\app\administrator\diag\rdbms\ortest\ortest\trace\ortest_ora_7784.trc
output = d:\app\20211213_tkprof.tra
即可查看编译后的文件。
 
3、如何得到真实的执行计划
在上面介绍了四种方法,除了第四种方法外,其他三种方法得到的执行计划都有可能是不准确的。在Oracle数据库中判断得到的执行计划是否准确,就是看目标SQL是否真正执行,真正执行过的SQL所对应的执行计划就是准的,反之则可能不准。注意,这里的判断原则从严格意义上来说并不适用于AUTOTRACE开关,因为所有使用AUTOTRACE开关显示的执行计划都有可能是不准的,即使对应的目标SQL实际上已经执行过,这一点在后会详细解释。
下面我们就用上述原则来判断除了第4中以外的其他三种方法中哪些方法得到的执行计划是准的,哪些是可能不准的。
对使用第一种方法(EXPLAIN PLAN)得到的执行计划而言,因为此时目标SQL并没有实际执行,所以用该方法得到的执行计划有可能是不准的,尤其是在目标SQL包含绑定变量时,在默认开启绑定变量窥探(Bind Peeking)情况下,对含有绑定变量的目标SQL使用explain plan得到的执行计划只是一个半成品,Oracle在随后对该SQL的绑定变量进行窥探后就得到额这些绑定变量具体的值,此时Oracle很可能会对上述半成品的执行计划做调整,一旦做了调整,使用EXPAIN PLAN命令得到的执行计划就不准了。
对于使用第二种方法(DBMS_XPLAN包)而言,针对不同的应用场景,你可以选择以下的一种:
select * from table(DBMS_XPLAN.display);
select * from table(DBMS_XPLAN.display_cursor(null,null,'advanced'));
select * from table(dbma_xplan.display_cursor('sql_id/hash_value',child_cursor_number,'advanced'));
select * from table(dbms_xplan.display_awr('sql id'));
显然select * from table(DBMS_XPLAN.display);所得到的执行计划可能是不准的。因为它知识用于查看使用expain plan命令得到的执行计划,目标sql此时还没有真正执行,所以用它得到的执行计划可能是不准的。使用剩下三种方式所得到的执行计划都是准的。因为此时SQL都已经被实际执行过。
对使用第三种方法(AUTO TRACE开关),可以使用如下三种方式中的一种开启AUTO TRACE开关:
set autotrace on
set autotrace traceonly
set autotrace traceonly explan
上述三种方式中,当使用set autotrace on和set autotrace traceonly时,SQL都已经被实际执行过了,真是因为被实际执行过,所以在此情况下我们能扩大农目标SQL的实际资源消耗情况。当使用set autotrace traceonly explan时,如果执行的是select语句,则该select语句并没有被Oracle实际执行,但如果执行的是DML语句,情况就不一样了,此时的DML语句是会被实际执行的。所以在使用上面三种方法来获得DML语句的执行计划要小心,因为这些DML语句实际上已经被执行了。
这里需要特别注意的是:虽然使用部分SET AUTOTRACE命令后SQL实际上已经被执行了,但是所有使用SET AUTOTRACE命令所得到的执行计划都有可能是不准的,因为autotrace命令所显示的执行计划都是来源于调用expain plan命令。
  

oracle之如何获取执行计划方法的更多相关文章

  1. Oracle中获取执行计划的几种方法分析

    以下是对Oracle中获取执行计划的几种方法进行了详细的分析介绍,需要的朋友可以参考下     1. 预估执行计划 - Explain PlanExplain plan以SQL语句作为输入,得到这条S ...

  2. ORACLE 获取执行计划的方法

    一.获取执行计划的6种方法(详细步骤已经在每个例子的开头注释部分说明了): 1. explain plan for获取: 2. set autotrace on : 3. statistics_lev ...

  3. oracle获取执行计划及优缺点 详解

    一.获取执行计划的6种方法(详细步骤已经在每个例子的开头注释部分说明了):1. explain plan for获取: 2. set autotrace on : 3. statistics_leve ...

  4. 获取执行计划——EXPLAN PLAN

    一般获取执行计划有四种途径:1.执行explain plan,查询结果输出表.2.查询动态性能视图,它显示缓存在库缓存中的执行计划(有时查不出结果是因为执行计划已经不在库缓存中).3.查询AWR或St ...

  5. 案例:使用dbms_xplan.display_cursor无法获取执行计划

    案例:使用dbms_xplan.display_cursor无法获取执行计划 环境:RHEL 6.5 + Oracle 11.2.0.4 在一次测试中发现使用dbms_xplan.display_cu ...

  6. 查看Oracle数据库中的执行计划

    1.set autotrace traceonly命令 2.explain plan for命令 1)explain plan for select * from dual; 2)select * f ...

  7. oracle中获取执行计划

    1. 预估执行计划 - Explain PlanExplain plan以SQL语句作为输入,得到这条SQL语句的执行计划,并将执行计划输出存储到计划表中. 首先,在你要执行的SQL语句前加expla ...

  8. Oracle(一)执行计划

    目录 一.什么是执行计划 二.如何查看执行计划 三.如何读懂执行计划 1. 执行顺序的原则 2. 执行计划中字段解释 3. 谓词说明 4. JOIN方式 4.1 HASH JOIN(散列连接) 4.2 ...

  9. Oracle性能优化之oracle中常见的执行计划及其简单解释

    一.访问表执行计划 1.table access full:全表扫描.它会访问表中的每一条记录(读取高水位线以内的每一个数据块). 2.table access by user rowid:输入源ro ...

  10. oracle 基础知识(十三)----执行计划

    一, 执行计划是什么? 一条查询语句在ORACLE中的执行过程或访问路径的描述.即就是对一个查询任务,做出一份怎样去完成任务的详细方案. 二,执行计划的查看 设置autotrace 序号 命令 解释 ...

随机推荐

  1. Vue框架整理:computed计算属性设置与缓存

    简单的一些小计算可以直接用模板内的表达式计算,比较复杂一点的就建议使用"计算属性来运算了",也方便后期的维护:vue所有的计算属性都以函数的形式写在Vue实例内的computed里 ...

  2. mysql的七种基本关联查询方式

    -- 内连接 SELECT last_name , department_name FROM employees e JOIN departments d ON e.department_id = d ...

  3. Intellij IDEA 通过数据库表生成带注解的实体类Generate MyPOJOs.groovy脚本的编写

    //两段代码第一个是mybatis-plus的 第二个spring-jpa的,jpa的是我复制别人的,是本体,mybatis的是我改的//idea连接数据方法见 https://www.cnblogs ...

  4. 【11】java之抽象类

    一.抽象类基本概念 1.1 抽象类 抽象类:是指在普通类的结构里增加抽象方法的组成部分,抽象类要使用 abstract 声明. 抽象方法:没有方法体且必须使用 abstract 关键字进行定义. 拥有 ...

  5. c# 游戏设计:地图移动

    想实现一个小游戏,先做地图移动.步骤记录如下: 1.百度到一张大的迷宫地图,放在项目的debug目录下,备用. 2.创建一个winform项目,不添加任何界面元素. 3.添加数据成员如下: Pictu ...

  6. 下拉刷新,上拉触底(.js里自带)

    <view>content值是{{cont}}</view> <button bindtap="add">+1</button>   ...

  7. Vicinity Vision Transformer概述

    0.前言 相关资料: arxiv github 论文解读 论文基本信息: 发表时间:arxiv2022(2022.6.21) 1.针对的问题 视觉transformer计算复杂度和内存占用都是二次的, ...

  8. cuda+pytorch环境安装

    本机cuda版本为v11.5 conda install cudatoolkit 使用 CUDA 11.3版本的配置 conda install pytorch==1.11.0 torchvision ...

  9. MessageUtil

    1 public abstract class MessageUtil { 2 3 public static String changeMsg(CustomerReportQueryObject q ...

  10. python命令行开发--click

    目录 前言 安装 快速上手 参考文档 前言 按照官方的介绍:Click 是一个利用很少的代码以可组合的方式创造优雅命令行工具接口的 Python 库. 它是高度可配置的,但却有合理默认值的" ...