6

osc_29179957的个人空间

 3 years ago
source link: https://my.oschina.net/u/5126455/blog/5082451
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何诊断SQL数据? - osc_29179957的个人空间 - OSCHINA - 中文开源技术交流社区

当一个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)在里面。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK