当一个SQL呈现性能问题时,能够应用SQL_TRACE 或者 10046事件来跟踪SQL,通过生成的trace来理解SQL的执行过程。咱们在查看一条SQL的执行打算的时候,只能看到CBO 最终通知咱们的执行打算后果,然而不晓得CBO 是依据什么来做的。如果遇到了执行打算异样,能够借助Oracle 10053事件进行跟踪。10053事件是oracle提供的用于跟踪sql语句成本计算的外部事件,它能记录CBO模式下oracle优化器如何计算sql老本,生成相应的执行打算。
通过session级别跟踪:
ALTER SESSION SET EVENTS='10053 trace name context forever, level 1';
或ALTER SESSION SET EVENTS='10053 trace name context forever, level 2';
执行相干sql
explain plan for select count(*) from obj$;
ALTER SESSION SET EVENTS '10053 trace name context off';
对特定session启用跟踪:
通过调用 DBMS_SYSTEM. SET_EV包实现
PROCEDURE SET_EV
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
SI BINARY_INTEGER IN
SE BINARY_INTEGER IN
EV BINARY_INTEGER IN
LE BINARY_INTEGER IN
NM VARCHAR2 IN
查问v$sessiowww.pizei.comn 视图获取过程信息
SQL> select sid,serial#,username from v$session where username is not null;
SID SERIAL# USERNAME
125 25 SYS
执行跟踪
exec dbms_system.SET_EV(125,25,10053,1,'');
完结跟踪
exec dbms_system.SET_EV(125,25,10053,0,'');
查问零碎对应session trace文件
select value from v$diag_info where name = 'Default Trace File';
通过开发人员确认该sql在测试库(LINUX+ 12.2.0.1 单机环境)执行只须要几秒即可(数据量相差不大)实现,其中bs_loan_card_addition、bs_loan_card、bs_loan_contract_addition三张表的数据量都在200万行左右。
获取到生产环境该sql执行打算如下:
测试环境该sql执行打算如下:
首先狐疑统计信息不精确导致CBO在页游拜访BS_LOAN_CARD表的时候抉择谬误,本应该抉择BS_LOAN_CARD_I3索引(因为CUSTOMER_NO"='1000193229’的选择性很好)而这也是开发设计这个索引的起因。但后果是抉择了BS_LOAN_CARD_I0索引(对应的是BS_LOAN_CARD.LOAN_CARD_NO,该列惟一的),而过滤条件基本没有这个列,他只是作为关联条件与bs_loan_card_addition表进行连贯。
因而首先查看统计信息,意外发现BS_LOAN_CARD.LOAN_CARD_NO,列上竟然存在一个HYBIRD类型的直方图,实践上来说该值的唯一性十分好,不应该收集直方图,因而间接删除了该列上的直方图,再次查看发现执行打算仍未扭转。
尝试应用10053对该SQL执行打算的产生过程进行跟踪,发现如下信息:
而且联合执行打算
这个执行打算简略了解来说就是首先对BS_LOAN_CARD_ADDITION进行全表扫描,而后在这个所得的后果集外面每一行的LOAN_CARD_NO列拿出来到BS_LOAN_CARD外面匹配,这就是第6部外面呈现了一个"B"."LOAN_CARD_NO"=:B1起因,而这个就是oracle改写后的后果。而从其抉择对BS_LOAN_CARD_ADDITION进行全表扫描就不可避免的导致了效率会很低。而且其后的rows 估算为2444K,这个是贴合理论的,所以之前的删除直方图不会有后果。而测试上的改写后果显著跟这个不一样,排除统计信息的影响,那么就开始狐疑cbo外部的算法抉择问题,再联合那个可疑 的 “CBQT bypassed forquery block UPD$1 (#0): Disabled by parameter. ”提醒,狐疑优化器参数在两个环境中有区别,
一:_optimizer_cost_based_transformation设为linear(默认值),其有如下值:
"exhaustive", "iterative","linear", "on", "off"。
本例中该参数就是默认值,该参数可管制是否容许CBO进行改写
二:_optimizer_squ_bottomup 参数值为true(默认值).
而生产环境中恰好相反为false,所以生产的trace中会有Disabled by parameter 字眼
_optimizer_squ_bottomup enables unnesting of subquery in a bottom-upmanner;
该参数默认为true,即开启子查问自底向上的开展性能(也就是相似unnest hint的性能),unnest称之为对子查问开展,顾名思义,就是不让子查问孤独地嵌套(nest)在外面。