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

一次谓词越界导致SQL执行计划变化的案例

原创 小张同学 2024-02-20
282

业务应用人员反馈某SQL平时执行速度很快,在中午13:30分节点的时候,执行了将近20分钟

数据库类型:Oracle RAC - 3节点 11204版本

接收到该需求的时候,第一时间在考虑该SQL的执行计划会不会因为某种原因发生了变化,导致SQL执行时间变长。

根据业务方提供的时间节点以及SQL文本,进行问题的排查。

set lin 200

col SAMPLE_TIME for a40

select sample_time,instance_number,NVL(ash.event, ‘ON CPU’) AS event,blocking_session,sql_id, CURRENT_OBJ#,count(*) from

dba_hist_active_sess_history ash

where sample_time>=to_timestamp(’&1’,‘yyyy-mm-dd hh24:mi:ss’)

and sample_time<=to_timestamp(’&2’,‘yyyy-mm-dd hh24:mi:ss’)

group by sample_time,instance_number,event,blocking_session,sql_id, CURRENT_OBJ#

order by 7;

以上的查询结果并结合ash报告,发现问题节点出现大量的gc等待;再查看了历史SQL执行情况,发现以前都是毫秒级别的执行结果,这次是需要执行接近2分钟,那么接下来的思路就是验证最开始的猜想,是否执行计划发生了变化。

段落引用
select * from table(dbms_xplan.display_awr(‘sqlid’));

通过历史执行计划查询,发现确实出现了两个不同的执行计划,两个执行计划很明显的不同点在于ABC三表关联顺序发生了变化,而该有的索引都存在,也都是vaild状态,再查看关联条件,为时间字段,通过分析SQL,该SQL是想查看两年前截止到目前最新一天以内的数据,这里直接做一个10053 event查看执行计划变化的原因。

exec dbms_sqldiag.dump_trace(p_sql_id => ‘SQLID’,p_child_number => 0,p_component => ‘Compiler’,p_file_id => ‘TEST_2024’);

在11204之后的版本中,可以通过执行DBMS_SQLDIAG.DUMP_TRACE这个方法来进行10053 event的分析。

但Oracle文档以及MOS上没有找到以上参数的含义,遂通过以下方法查看,毕竟不知道执行了该方法是否会对生产环境造成影响。

more $ORACLE_HOME/rdbms/admin/dbmsdiag.sql

P_SQL_ID : 指定要分析的SQLID
P_CHILD_NUMBER : SQL的子游标Number,我这里通过V$SQL查询到有问题的子游标number,就是0
P_COMPONENT : Trace的级别,默认为Optimzer,还有一个级别为Compiler,比Optimzer输出信息更详细
P_FILE_ID : 输出文件的标识字符串,为即将产生的10053 trace文件打上一个自定义标识符

最后在生成的10053 trace文件中发现了以下关键词

Using prorated density: 3.6616e-04 of col #62 as selectivity of out-of-range/non-existent value pred

至此确定为谓词越界导致的SQL执行计划发生变化,原本毫秒时间内可以执行完毕的SQL,变成了现在要接近2分钟执行完,而且该SQL为业务高频执行的SQL,RAC各节点间的数据加载读取过程中,由于执行时间的变长,执行频率的不变(高频),导致出现了大量的gc等待。

总结

判断谓词越界的方法不止10053 event,例如还可以通过统计信息查询high value以及low value根据传入的值来进行比较判断是否出现谓词越界;那么谓词越界为什么会产生执行计划的变化呢,这是因为输入了一个统计信息中不存在的值,导致CBO无法根据这个值来进行路径cost正确的计算,CBO错误的将这个值固定成一个不正确的选择率,cost计算出现了偏差,导致了执行计划重新生成,并选择了这个CBO以为当前情况最“正确”的执行计划。

解决方案也有好几种:由于该SQL涉及的多数为大表,根据条件过滤的时间字段也在大表上,使用的也是绑定变量,所以可以选择绑定执行计划,或者将该大表的自动统计信息收集阈值进一步调低,比如默认的变化10%进行收集,改成变化1%,或者改成每一天都强制进行收集等等。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论