一次典型的 SQL 性能问题排查:临时表导致的隐藏性能陷阱

在日常数据库运维过程中,经常会遇到这样一类问题:

数据库整体性能正常,但某一条 SQL 在业务系统中执行极慢,

然而 DBA 在后台手工执行时,却发现 执行速度非常快。

这类问题往往不在"数据库整体性能",而隐藏在具体 SQL 的执行细节和业务执行环境差异中。

本文记录了一次真实的 SQL 性能排查过程,最终定位到 临时表使用不当 所引发的问题。

一、问题现象:整体正常,单条 SQL 异常

客户业务系统运行过程中,出现如下现象:

• 数据库整体运行状态正常

• CPU、IO、等待事件均无明显异常

• 仅有 一条业务 SQL 在前台执行非常缓慢

• 同一条 SQL 在后台手工执行时,执行速度却非常快

从表象来看,这并不像是数据库整体性能瓶颈,更像是某条 SQL 在特定执行场景下存在问题。

二、通过 AWR 报告定位性能热点

为进一步确认问题,通过 AWR 报告(使用 @?/rdbms/admin/awrrpti.sql 生成)对系统性能进行分析。

AWR 报告显示:

• 系统的主要性能消耗集中在 一条 SQL

• 该 SQL 单次执行时间约为 406,814 ms

从执行时间来看,这条 SQL 明显是当前系统的主要性能瓶颈。

三、执行计划"完美",却解释不了慢的问题

继续查看该 SQL 的执行计划,发现一个容易让人放松警惕的情况:

• 执行计划 cost 不大

• 各个执行步骤看起来都非常合理

• 没有明显的全表扫描或低效访问路径

从执行计划角度判断,这条 SQL 理论上不应该这么慢。

但事实是:

SQL 确实执行得非常慢。

四、执行统计信息暴露异常:buffer gets 极高

在进一步查看 SQL 的执行统计信息后,问题开始显现出来。

该 SQL 的统计信息显示:

• buffer gets 达到 595,764,242

• 这是一个极不正常的数值

而从数据规模来看:

• SQL 中涉及的最大表 GL_VERIFY_LOG 只有 17,710 行

• 其他表的数据量更是可以忽略不计

在如此小的数据规模下,却出现如此高的 buffer gets,显然不符合正常逻辑。

五、常规思路排查:统计信息并非根因

第一反应自然是怀疑:

是否因为对象统计信息不准确,导致优化器判断失误?

于是对 SQL 涉及的所有对象进行了 100% 采样的统计信息收集。

但结果是:

• SQL 执行性能没有任何改善

• buffer gets 依然很高

同时可以确认:

• SQL 未使用绑定变量

• 不存在 bind peeking 导致的执行计划不稳定问题

• 后台执行时显示的执行计划,与 AWR 中的执行计划一致

此时,执行计划、统计信息、SQL 写法,似乎都"没有问题"。

六、关键细节:执行计划中的 Dynamic Sampling

在反复对比前台与后台执行差异时,注意到一个细节:

后台执行该 SQL 时,执行计划中出现了 Dynamic Sampling(动态采样)。

这是一个非常关键的信号。

在 Oracle 中,涉及临时表的 SQL,往往会触发动态采样,以便在运行时获取更准确的数据分布信息。

这一现象直接将排查方向指向了 SQL 中可能存在的临时表。

七、问题根因确认:临时表数据量差异

继续深入检查 SQL 涉及的对象,最终确认:

• SQL 中使用了临时表 ASSTEMPORA

• 前台业务程序执行 SQL 前,会向该临时表中加载 大量数据

• 后台 DBA 手工执行 SQL 时,该临时表 数据为空

这就解释了所有现象:

• 前台执行:

• 临时表数据量大

• SQL 执行过程中产生大量 buffer gets

• 导致执行时间极长

• 后台执行:

• 临时表无数据

• SQL 执行路径看起来"非常理想"

• 执行时间极短

八、优化方案:为临时表补充索引

问题的本质在于:

临时表在高数据量参与 SQL 计算时,缺失必要索引。

针对该问题,在临时表 ASSTEMPORA 上创建索引:

复制代码
CREATE INDEX ASSTEMPORA_IDX ON ASSTEMPORA (assid);

索引创建完成后:

• 前台 SQL 执行时间明显缩短

• buffer gets 大幅下降

• 业务模块性能恢复正常

问题得到彻底解决。

九、小结:临时表同样需要"正式对待"

通过这次问题排查,可以得到几个非常重要的经验结论:

  1. 执行计划看起来没问题,并不代表 SQL 一定高效

  2. 前台与后台执行差异,往往来自 数据状态不同

  3. 临时表一旦承载真实业务数据,就必须像普通表一样设计索引

  4. 执行计划中的 Dynamic Sampling 是一个非常重要的排查线索

很多 SQL 性能问题,并不是写得复杂,而是在真实业务场景下,被放大了原本被忽略的设计缺陷。

相关推荐
海山数据库2 分钟前
移动云大云海山数据库(He3DB)postgresql_anonymizer插件原理介绍与安装
数据库·he3db·大云海山数据库·移动云数据库
l1t3 分钟前
DeepSeek总结的PostgreSQL的GPT推理SQL移植到DuckDB的性能优化方法
sql·gpt·postgresql
云飞云共享云桌面6 分钟前
高性能图形工作站的资源如何共享给10个SolidWorks研发设计用
linux·运维·服务器·前端·网络·数据库·人工智能
2501_9279935314 分钟前
SQL Server 2022安装详细教程(图文详解,非常详细)
数据库·sqlserver
星火s漫天15 分钟前
第一篇: 使用Docker部署flask项目(Flask + DB 容器化)
数据库·docker·flask
xcLeigh20 分钟前
Python 项目实战:用 Flask 实现 MySQL 数据库增删改查 API
数据库·python·mysql·flask·教程·python3
威迪斯特21 分钟前
Flask:轻量级Web框架的技术本质与工程实践
前端·数据库·后端·python·flask·开发框架·核心架构
xu_yule22 分钟前
Redis存储(15)Redis的应用_分布式锁_Lua脚本/Redlock算法
数据库·redis·分布式
一灰灰blog39 分钟前
Spring AI中的多轮对话艺术:让大模型主动提问获取明确需求
数据库·人工智能·spring
Nandeska1 小时前
15、基于MySQL的组复制
数据库·mysql