暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【测试方法】简谈Oracle执行计划

非功能之路 2021-06-10
667

1.引言

      有一句人生至理名言这么说:只要路是对的,就不怕路远。意思就是只要前进的方向是正确的,路是可以走通的,顺着这条路前行,不论经过多少曲折,不论历经多少艰辛,最终一定能够到达成功的彼岸;同样,在非功能测试过程中,会遇到各种各样的原因导致的性能问题,其中,由于数据库SQL执行计划原因造成的性能瓶颈还是占绝大多数的。SQL本身的执行方式决定了性能的好坏,而反映SQL执行方式的唯一证明就是执行计划,这里,执行计划就好比是路,只要执行计划合理,那么就无需担心数据库性能问题,可见执行计划是非常重要的。

2.简介

       获得一个SQL语句的执行计划有多种方式,有很多图形化的工具,如Toad、OEM等能产生图形化的执行计划,这里我只介绍一下Oracle自带的方法,即最原始的文本方式。

        Explain plan for…是最简单的获得执行计划的方法,这个命令通过生成指定的SQL的执行计划,并把执行计划保存到用户指定的表中供用户查询,注意,它并不会保存在Library cache中。Oracle 10g以上版本提供了DBMS_XPLAN系列方法,它获得的是Library Cache中的内容,是最真实的执行计划。这个方法综合利用了V$SQL_PLAN、V$SQL_PLAN_STATISTICS、V$SQL_WORKAREA、V$SQL_PLAN_STATISTICS_ALL几个视图中获得数据。

2.1基本视图介绍

       V$SQL_PLAN视图和PLAN_TABLE类似,可以查看执行计划。所不同的是,借助这个视图查看到的是在Library cache中的真实的执行计划。

        V$SQL_PLAN_STATISTICS视图查看的是执行计划的每一步骤在运行时的统计信息,包括花费时间、处理的数据行数。这个视图的数据是对V$SQL_PLAN有益的补充,前一个视图虽然也有类似的数据,但是那些数据是在Parsing阶段预估出来的,是供优化器引擎选择最优的执行计划用的,而这个视图提供的是真正的性能消耗。但是在缺省时,这些数据并不会收集,要想收集这些数据,必须把初始化参数STATISTICS_LEVEL设置成ALL级别,或者对SQL语句添加GATHER_PLAN_STATISTICS提示。

         V$SQL_WORKAREA视图提供了SQL语句运行时SQL Workarea内存的消耗。

         V$SQL_PLAN_STATISTICS_ALL视图是对前3个视图的一个汇总,通过这一个视图就可以获得3个视图的信息,Oracle替用户完成了复杂的JOIN操作。

        V$SESSION是做性能调整最初的入口。这个视图会记录2条SQL语句,包括目前正在执行和刚刚执行完的这样2条SQL语句,对应的列分别是SQL_ID、SQL_CHILD_NUMBER(当前正在执行的)和PREV_SQL_ID、PREV_CHILD_NUMBER(刚刚执行完的)。

        了解了以上基础数据后,下面介绍如何获得这些数据,使用的是DBMS_XPLAN 包。其中,DISPLAY方法是Oracle 9i中的,Oracle 10g以上版本新增了如下方法,DISPLAY_CURSOR、DISPLAY_AWR、DISPLAY_SQLSET、DISPLAY_SQL_PLAN_BASELINE,新增的这些方法的好处在于不需要重新执行SQL语句,就立即可以从Shared Pool中获得执行计划,而且得到的是真实的执行计划,而不是估计的执行计划。

2.2生成与查看执行计划

1) Oracle 9i : Explain Plan For

A、生成指定语句的执行计划,如图1:

   SQL> explain plan for select * from alctdoc where alctdoc_id=’110733600201501230207’;

图1 生成执行计划

B、查看语句的执行计划,如图2:

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

图2 查询执行计划

2) Oracle 10g:DISPLAY_CURSOR

Oracle 10g中推荐使用的方法是DISPLAY_CURSOR,格式声明如下:

DBMS_XPLAN. DISPLAY_CURSOR(

Sql_id    IN VARCHAR2   DEFAULT     NULL,

Child_number      IN NUMBER       DEFAULT     NULL,

Format   IN VARCHAR2   DEFAULT     ‘TYPICAL’);

针对其中参数进行以下说明。

SQL_ID:代表SQL语句的ID;

CHILD_NUMBER:一个SQL语句可能有多个子游标(Child Cursor);如果不指定值,会罗列出所有子游标的执行计划;

FORMAT:这个参数用来控制输出内容,最常见的4种内置格式有:BASIC、TYPICAL、SERIAL、ALL。

A、执行SQL语句,如图3:

图3 执行SQL

 B、确认这个语句的SQL_ID,如图4:

图4 查询SQL_ID

C、以TYPICAL格式查看执行计划,如图5:

图5 查看执行计划

3) Oracle 10g:DISPLAY_AWR

         DISPLAY _AWR 方法是作为Oracle 10g诊断包的一部分发布的,用户借助这个方法可以获得AWR中的执行计划,其信息来自于DBA_HIST_SQL_PLAN、DBA_HIST_SQLTEXT。

       DISPLAY _AWR 方法的声明如下:

         DBMS_XPLAN.DISPLAY_AWR(

Sql_id    IN   VARCHAR2,

Plan_hash_value  IN   NUMBER     DEFAULT NULL,

Db_id    IN   NUMBER     DEFAULT NULL,

Format   IN   VARCHAR2 DEFAULT     TYPICAL);

         AWR产生的报告中会带有SQL ID一列,如下图6所示,把这个值作为第一个参数传递给方法,就可以获得当时的执行计划。

图6 AWR报告

DISPLAY _AWR 方法的调用示例如下,相应生成的执行计划如下图7所示。

SQL> select  *  from table(dbms_xplan.display_awr(‘f318xdxdn0pdc’));

2.3如何阅读执行计划?

        执行计划输出包含5部分:SQL概要信息、执行计划、Query Block(QB)、数据过滤(谓词)、列投影。

A、 SQL概要信息:包含SQL_ID、Child Number(SQL语句的Child Number)、完整的SQL文本

B、  执行计划:包含执行计划的hash值;以表格的形式显示执行计划,根据Format参数的设置,这个表格的列会有不同。

C、  Query Block主要用于提示(Hint)。Oracle的Hint是一个非常强大的性能调整工具,借助于它可以控制SQL语句的执行计划,但是Hint的作用范围是经常容易被忽略的限制条件。

D、 数据过滤(Predicate Information),更通常的叫法是过滤条件,包括选择条件、连接条件等,这一部分的格式如下:

4 – acess (“E”.”DEPTNO”=”D”.”DEPTNO”)

5 – fliter (“E”.”SAL”>300)

每一行都是一步数据过滤,记录了过滤是在执行计划的哪一行(4或5行)起作用,以及如何(acess、filter)起作用的。

Filter:代表对原始数据的过滤条件。

Acess:代表利用某种结构过滤数据,比如利用索引、Hash连接等。

执行计划中每个使用数据过滤的行前,也会带有一个*号,和这里的代表行号的数字相对应。

E、列投影(Column projection):投影是关系数学的术语,含义就是只选择部分列而非所有列。Oracle是一个关系型数据库,而关系数学正是关系型数据库的理论基石。这一部分显示了每一个操作返回了哪些列,以及这些列的数据类型、数据长度。从这里,我们可以判断是否发生了隐式数据转换,而隐式数据类型转换正是阻止使用索引的罪魁祸首之一。

3.结束语

       以上简单介绍SQL语句执行计划的获得方法和阅读方式,真正读懂执行计划,进行性能调优,还需要在实践中不断积累经验;记住:路很关键,只要路是对的,就不怕路远。

文章转载自非功能之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论