*********************************************************** ----1:获取“刚刚”的执行计划display_cursor *********************************************************** Explain plan命令在Oracle中,可以对后面的SQL语句进行直接的解析,将执行计划保存在一个plan_table的中间表中。之后通过dbms_xplan包的方法进行获取。 select count(*) from t1; --查询v$sql视图,找到该语句的sql_id(前提是你要查询的sql语句还在shared pool): select sql_id from v$sql where sql_text='select count(*) from t1'; SQL_ID ------------- 5bc0v4my7dvr5 --调用dbms_xplan包,查看该语句执行时的实现执行计划: select * from table(dbms_xplan.display_cursor('5bc0v4my7dvr5')); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- SQL_ID 5bc0v4my7dvr5, child number 0 ------------------------------------- select count(*) from t1 Plan hash value: 3724264953 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 74 (100)| | | 1 | SORT AGGREGATE | | 1 | | | PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- | 2 | TABLE ACCESS FULL| T1 | 100K| 74 (2)| 00:00:01 | ------------------------------------------------------------------- Note ----- - SQL plan baseline SQL_PLAN_f4251dfwsquh4616acf47 used for this statement 已选择18行。 /************* 直接调用display_cursor,不指定sql_id,就可以将刚刚当前会话执行的SQL命令执行计划从library cache中查询出来。 注意:display_cursor也支持format参数,可以进行详细执行计划信息的抽取。 只能在sqlplus或者sqlplusw上使用。如果是TOAD、PL/SQL develop等其它三方工具,可能调用不能正常使用。 ***********/ *********************************************************** 2:explain plan for *********************************************************** ---案例1、显示简单的计划 explain plan for select count(*) from t1; 查看结果: select * from table(dbms_xplan.display()); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 3724264953 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 74 (2)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T1 | 100K| 74 (2)| 00:00:01 | ------------------------------------------------------------------- Note PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- ----- - SQL plan baseline "SQL_PLAN_f4251dfwsquh4616acf47" used for this statement 已选择13行。 --案例2、显示详细执行计划信息 explain plan for select count(*) from t1; 查看结果: select * from table(dbms_xplan.display(null,null,'advanced')); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 3724264953 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 74 (2)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T1 | 100K| 74 (2)| 00:00:01 | ------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- ------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / T1@SEL$1 Outline Data ------------- /*+ BEGIN_OUTLINE_DATA FULL(@"SEL$1" "T1"@"SEL$1") PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- OUTLINE_LEAF(@"SEL$1") ALL_ROWS DB_VERSION('11.2.0.3') OPTIMIZER_FEATURES_ENABLE('11.2.0.3') IGNORE_OPTIM_EMBEDDED_HINTS END_OUTLINE_DATA */ Column Projection Information (identified by operation id): ----------------------------------------------------------- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- 1 - (#keys=0) COUNT(*)[22] Note ----- - SQL plan baseline "SQL_PLAN_f4251dfwsquh4616acf47" used for this statement 已选择38行。 SQL> /**** Explain plan for使用起来非常顺手,特别是可以支持第三方开发工具中使用,但是explain plan在使用的时候,有些 小问题,需要我们注意: 1、explain plan for是单纯对SQL语句进行优化器分析,获取并产生到的执行计划。 这个过程中,并没有真正执行。所以,生成的执行计划有时候会可能有问题,而且进行统计的信息情况没有 autotrace的准确度高; 2、explain plan for由于只是对执行计划进行估计。所以在有绑定变量的SQL时,生成的执行计划并不准确; *****/ *********************************************************** 3、autotrace工具使用 *********************************************************** *************3.1 配置AUTOTRACE 配置AUTOTRACE 的方法不止一种,以下是我采用的方法: 1、 (1)cd [ORACLE_HOME]/sqlplus/admin; (2)作为SYS 或SYSDBA 登录SQL*Plus; (3)运行@/plustrce.sql; (4)运行GRANT PLUSTRACE TO PUBLIC。 如果愿意,可以把GRANT TO PUBLIC 中的PUBLIC 替换为某个用户。 通过将PLAN_TABLE置为public,任何人都可以使用SQL*Plus 进行跟踪。这么一来,就不需要每个用户都安装自己的计划表 --配置如下:想配置scott下使用autotrace --1.查看scott是否具有权限 C:\>sqlplus scott/tiger@orcl SQL> show user; USER 为 "SCOTT" SQL> set autotrace on; SP2-0618: 无法找到会话标识符。启用检查 PLUSTRACE 角色 SP2-0611: 启用 STATISTICS 报告时出错 --2.作为SYS 或SYSDBA 登录SQL*Plus运行@/plustrce.sql SQL> show user; USER 为 "SYS" SQL> @E:\app\Administrator\product\11.2.0\dbhome_1\sqlplus\admin\plustrce.sql 返回:---------------------------------- SQL> drop role plustrace; drop role plustrace * 第 1 行出现错误: ORA-01919: 角色 'PLUSTRACE' 不存在 SQL> create role plustrace; 角色已创建。 SQL> SQL> grant select on v_$sesstat to plustrace; 授权成功。 SQL> grant select on v_$statname to plustrace; 授权成功。 SQL> grant select on v_$mystat to plustrace; 授权成功。 SQL> grant plustrace to dba with admin option; 授权成功。 SQL> SQL> set echo off ------------------------------------- --3.授权给scott账户 SQL> grant plustrace to scott; 授权成功。 --4.scott账户验证是否具有权限 SQL> show user; USER 为 "SCOTT" SQL> set autotrace on; SQL> set autotrace traceonly; SQL> set timing on; *************3.2 autotrace工具使用 SQL> set autotrace 用法: SET AUTOT[RACE] {OFF | ON | TRACE[ONLY]} [EXP[LAIN]] [STAT[ISTICS]] --用法1:查看执行计划、统计信息并且返回sql结果集 set autotrace on; select count(*) from t; COUNT(*) ---------- 50295 已用时间: 00: 00: 00.01 执行计划 ---------------------------------------------------------- Plan hash value: 2966233522 ------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 159 (2)| 00:00:02 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | TABLE ACCESS FULL| T | 50295 | 159 (2)| 00:00:02 | ------------------------------------------------------------------- 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 509 bytes sent via SQL*Net to client 211 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 1 rows processed ---方法2:查看执行计划、统计信息不返回sql结果集: SQL> set autotrace traceonly; SQL> select * from t2; 已选择402344行。 执行计划 ---------------------------------------------------------- Plan hash value: 1513984157 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 402K| 33M| 1240 (3)| 00:00:15 | | 1 | TABLE ACCESS FULL| T2 | 402K| 33M| 1240 (3)| 00:00:15 | -------------------------------------------------------------------------- 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 911 bytes sent via SQL*Net to client 190 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 402344 rows processed ---方法3:只看执行计划不返回sql结果集: QL> set autotrace traceonly explain; SQL> select * from t; 已用时间: 00: 00: 00.01 执行计划 ---------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 50295 | 4273K| 161 (3)| 00:00:02 | | 1 | TABLE ACCESS FULL| T | 50295 | 4273K| 161 (3)| 00:00:02 | ---方法4:只看统计信息不返回sql结果集: SQL> set autotrace traceonly statistics; SQL> select * from t; 已选择50295行。 统计信息 ---------------------------------------------------------- 0 recursive calls 0 db block gets 0 consistent gets 0 physical reads 0 redo size 911 bytes sent via SQL*Net to client 189 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 50295 rows processed *********************************************************** 4、SQL_TRACE会话跟踪 *********************************************************** 当SQL语句出现性能问题时,我们可以用SQL_TRACE来跟踪SQL的执行情况,通过跟踪,我们可以了解一条SQL或者PL/SQL包的运行情况,SQL_TRACE命令会将SQL执行的整个过程输出到一个trace文件中,我们可以读这个trace 文件来了解在这个SQL执行过程中Oracle 都做了哪些操作。 可以通过sql命令启动SQL_TRACE,或者在初始化参数里面。 SQL>alter session set sql_trace=true; 或者 SQL> alter database set sql_trace=true; 这两条命令的区别: 在session级别设置,只对当前session进行跟踪,在实例级别,会对实例上所有的SQL做跟踪,这种方式跟踪的SQL太多, 代价是非常大的,所有很少用。 如果是在初始化文件里面设置,只需要在参数文件里添加一个sql_trace 参数即可。 示例: 1.确定当前的trace文件。 1.1 通过设置trace 文件标识 SQL> alter session set tracefile_identifier='ocpyang'; 会话已更改。 设置标识的目的就是方便我们查找生成的trace文件。我们只需要在trace目录查找文件名里带有标识的文件即可。 在Oracle 10g中,SQL_TRACE生成的trace文件默认路劲是$ORACLE_BASE/admin/SID/udump. 到了11g,trace 默认路径在:$ORACLE_BASE/diag/rdbms/orcl/orcl/trace目录下. 1.2直接用如下SQL直接查出,当前的trace文件名。 SELECT d.VALUE || '/' || LOWER (RTRIM (i.INSTANCE, CHR (0))) || '_ora_' || p.spid || '.trc' AS "trace_file_name" FROM (SELECT p.spid FROM v$mystat m, v$session s, v$process p WHERE m.statistic# = 1 AND s.SID = m.SID AND p.addr = s.paddr ) p, (SELECT t.INSTANCE FROM v$thread t, v$parameter v WHERE v.NAME = 'thread' AND (v.VALUE = 0 OR t.thread# = TO_NUMBER (v.VALUE)) ) i, (SELECT VALUE FROM v$parameter WHERE NAME = 'user_dump_dest' ) d; trace_file_name -------------------------------------------------------------------------------- E:\app\Administrator\diag\rdbms\orcl\orcl\trace/orcl_ora_68612.trc 2. 启动SQL_TRACE SQL> alter session set sql_trace=true; 会话已更改。 3. 进行相关事务操作 SQL> select * from t1; 4.关闭SQL_TRACE SQL> alter session set sql_trace=false; 会话已更改。 注意,这里是显示的关闭SQL_TRACE,在session级别,也可以直接退出SQLPLUS来终止SQL_TRACE。 *********************************************************** 5、10046跟踪 *********************************************************** 10046 事件主要用来跟踪SQL语句,它并不是ORACLE 官方提供给用户的命令,在官方文档上也找不到事件的说明信息。 但是用的却比较多,因为10046事件获取SQL的信息比SQL_TRACE 更多。 更有利于我们对SQL的判断。 10046事件说明10046事件是Oracle提供的内部事件,是对SQL_TRACE的增强. 10046事件可以设置以下四个级别: 1 - 启用标准的SQL_TRACE功能,等价于sql_trace 4 - Level 1 加上绑定值(bind values) 8 - Level 1 + 等待事件跟踪 12 - Level 1 + Level 4 + Level 8 类似sql_trace,10046事件可以在全局设置,也可以在session级设置。 开启10046事件 1.对当前session 使用10046事件 SQL>alter session set events ‘10046 trace name context forever, level 12’; --启动10046事件 执行相关事务 SQL>alter session set events ‘10046 trace name context off’; -- 关闭10046事件 2.对其他的会话进行跟踪 2.1用SQL_TRACE跟踪 SQL> select sid,serial# from v$session where SID=267; SID SERIAL# ---------- ---------- 267 996 SQL> execute dbms_system.set_sql_trace_in_session(267,996,true); -- 启动SQL_TRACE PL/SQL 过程已成功完成。 SQL> execute dbms_system.set_sql_trace_in_session(267,996,false); -- 关闭SQL_TRACE PL/SQL 过程已成功完成。 2.2 使用10046 事件跟踪 SQL> exec dbms_monitor.session_trace_enable(267,996,waits=>true,binds=>true); -- 启动trace PL/SQL 过程已成功完成。 SQL> exec dbms_monitor.session_trace_disable(267,996); -- 关闭trace PL/SQL 过程已成功完成。 注意: 如果一条SQL语句中包含了通过DBLINK进行的数据操作,我们想对这条SQL进行trace跟踪,在本地只能够 trace到本地执行的SQL信息,而对于远程的SQL语句,由于它运行在远端的数据库上,我们要获得它的信息, 需要到远端的数据库上,找到运行这条SQL语句的session,然后对它做Trace。 另外,这条SQL语句的执行 计划也只能从远端数据库上捕获到。 总之,当SQL语句操作出现性能问题时,我们可以用SQL_TRACE 或者10046事件进行跟踪是最合适的。 如果是数据库整体性能下降,就需要使用statspack或者AWR对数据库进行分析。