IT 邦德

陷阱太坑了,执行计划一模一样,速度差100倍!

某分析系统凌晨ETL作业突然超时告警,DBA团队立即介入排查。发现一个SQL执行时间从平时的0.5秒暴涨至500秒,导致后续流程全部阻塞。

初步检查显示,SQL文本、执行计划"完全一致",但性能差异达到100倍。更令人困惑的是,这个ETL调度的SQL一直运行正常长达1年多。

执行计划看似相同,实际执行效率却可能因隐性因素产生巨大差异。在这里小编将剖析三大根因,并给出根治方案。

1.统计信息不准

执行计划依赖统计信息生成,但若统计信息未及时更新,采样比率不合理,过时的直方图等优化器可能误判数据量。

Image
1.对比历史执行计划细节
通过SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id=>'xxx'))

2.适当调整DB统计信息默认采用比率

select dbms_stats.get prefs('estimate_percent') from dual;

BEGIN
    DBMS_STATS.SET_TABLE_PREFS(
        OWNNAME => 'SCHEMA_NAME',  -- 替换为表所属的用户名(模式名)
        TABNAME => 'TABLE_NAME',   -- 替换为表名
        PNAME   => 'ESTIMATE_PERCENT',
        PVALUE  => '50' -- 设置采样比例(例如 50 表示 50% 的采样率)
    );
END;

3.收集直方图
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT', 
tabname=>'ORDERS', 
method_opt=>'FOR ALL COLUMNS SIZE AUTO'); 

2.绑定变量窥视

月初查询的日期范围更大,但基于历史统计信息生成的计划未及时调整。

所谓绑定变量窥视,就是指oracle在第一次解析SQL语句的时候(也就是说该SQL第一次传入shared pool),会将你输入的绑定变量的值带入SQL语句里,从而參考你的字面值来推測该SQL大概会返回多少条记录,从而得到优化的运行计划。然后,以后再次运行同样的SQL语句时,不再考虑你所输入的绑定变量的值,直接取出第一次生成的绑定变量。

3.高水位、碎片影响

Oracle高水位线(HWM)和碎片会显著影响SQL执行效率。

高水位线标记了表曾使用的最大数据块范围,即使数据被删除,HWM也不会自动降低,导致全表扫描时仍需读取HWM下的所有空块(即使无数据),产生大量无效I/O。

例如,删除表中99%数据后,全表扫描耗时仍接近原水平,因HWM未重置。碎片则因频繁增删改导致数据块分布离散,增加磁盘寻址开销,降低缓存命中率,同时可能引发行迁移/链接,进一步拖慢查询。

综上,HWM和碎片会直接导致I/O负载激增和资源浪费,需结合统计信息维护和物理重组手段治理。

解决方案:定期使用SHRINK SPACE或MOVE重组表以降低HWM(需注意锁问题)对频繁删除的表采用TRUNCATE而非DELETE彻底重置HWM,通过统计信息监控碎片率并优化存储参数。

Image

总结

DBA的终极战场往往隐藏在细节中——统计信息、绑定变量、数据分布这些“看不见的参数”才是性能稳定的关键,建议读者定期执行以下操作:

对核心表每周检查统计信息时效性

通过AWR/ASH报告分析Top SQL变化趋势

建立SQL性能基线库,对比历史执行特征

正如一位资深DBA所言:“执行计划的一致性≠性能一致性,真正的优化藏在数据与资源的动态平衡中”

在您的工作中,是否遇到过执行计划"撒谎"的情况?欢迎在评论区分享您的经验!