10046是一个Oracle的内部事件(event),通过设置这个事件可以得到Oracle内部执行系统解析、调用、等待、绑定变量等详细的trace信息,即帮助我们解析一条/多条SQL、PL/SQL语句的运行状态,这些状态包括:Parse/Fetch/Execute三个阶段中遇到的等待事件、消耗的物理和逻辑读、CPU时间、执行计划等。它不仅为我们揭示了一条、多条SQL的运行情况,同时还能帮我们分析一些DDL维护命令的内部工作原理,RMAN、Data Pump Expdp/impdp等工具缓慢问题。对于SQL性能优化、分析系统的性能有着非常重要的作用。

             10053:我们可以通过10046事件看到一个SQL的执行的统计信息,以及执行计划,但是我们只看到了CBO最终告诉我们的执行结果,却并不知道CBO为什么要这么选择,那么就可以通过10053事件来生成SQL分析的整个过程到trace文件中,通俗点讲10053跟踪选路过程,10046产生结果。(10053可参考链接:https://blog.51cto.com/5073392/1308900)

             10046最常用的操作步骤(10053步骤类似,把事件改成10053就行,但是10053 TRC不能通过tkprof格式化)

1.开启10046跟踪事件

alter session set events '10046 trace name context forever, level 12';

如果想更容易标识trace文件,在开启事件之前,可以先设置trace的标识

alter session set tracefile_identifier='lych';

2.执行要跟踪的sql语句(对应的trace文件中有SQL的执行情况)

select * from lych;

3.停止10046事件跟踪

alter session set events '10046 trace name context off';

4.定位此次生成的trace文件

select distinct(m.sid),p.pid,p.tracefile from v$mystat m,v$session s,v$process p where m.sid=s.sid and s.paddr=p.addr;

5.用tkprof工具格式化文件输出

tkprof /source.trc /new.trc aggregate=yes sys=yes wait=yes sort=fchela

explain:参数格式为explain=username/password@server_name 或者explain=username/password,这个参数是通过执行explain plan语句来做到的,在trace文件中找到每个sql语句,提供一个执行计划。一般不是必要情况,指定这个参数并不可取,一旦指定了无效的信息,在输出的文件就会出现error。

table:table参数只和explain参数一起使用,用来指定某个表被explain plan语句使用来生成执行计划,通常尽量避免使用table参数,这里就不详细说明不常用的参数了,大家想要了解的话,可以查看oracle的官方联机文档。

print:参数用来限制输出文件生成的sql语句的数量,默认是无限制的。eg:只输出10个sql语句,则参数指定print=10,一般和sort参数一起使用才具有一定的意义。

insert:生成sql脚本,脚本可以用来把数据存储到数据库中。eg:insert=load_data.sql 。

sys:参数执行sys用户下运行的sql语句是否写入到输出文件,默认为yes。可设置为no,避免输出不必要的信息,这个看情况而定吧。

sort:排序的意思,指定输出文件里面的sql语句的顺序,默认是trace源文件里面的sql顺序。你可以指定根据cpu时间,物理读的块数,调用次数等进行排序,eg:sort=elapsed,disk —多个排序用逗号隔开。

aggregate:参数指定是否合并相同的sql,默认为yes,设置为no,输出文件就会列出每个sql的消耗情况等信息。用得比较多的一般是sys和aggregate参数。

        实操记录:

                    昨天生产其中一个PDB出现很奇怪的现象,库中每个表,视图查询都很慢,经过多次查询,发现不管什么SQL执行都超过3秒,利用explain plan for打印执行计划的时候,明显能感觉出来,SQL解析非常慢,第一想法猜测是数据字典出现问题,才没打印其他日志信息的时候 ,在SYS下执行了以下两个包:1 exec dbms_stats.gather_dictionary_stats  2 exec dbms_stats.gather_fixed_objects_stats,之后发现依然还是有问题。之后执行一些经过缓存的SQL发现执行非常快,没有对应的异常现象,这个时候我就已经猜到肯定是解析的时候出现的ORACLE内置递归操作出现了问题,于是根据推测打印了10046 TRC,发现其中一条递归SQL执行了3秒多,相当于这个库任何一条SQL,只要是没缓存的,起步时间都是3秒起步。查阅MOS资料后发现这是12c 12.1.0.2新特性“optimizer_adaptive_features”,默认是打开的,这个特性会在执行sql的时候自动收集统计信息.关闭对应参数后 system set optimizer_adaptive_features=false scope=both sid='*'一切恢复正常; 也可以通过关闭隐含参数实现:

alter system set "_OPTIMIZER_DSDIR_USAGE_CONTROL"=0 SCOPE=BOTH SID='*',当然这是一个BUG,也可以打补丁实现,Oracle Database 12c 版本1的自适应特性的建议 (Adaptive Features, Adaptive Statistics 以及 12c SQL 性能) (文档 ID 2297986.1)