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

一条烂 SQL 干爆一个库,Oracle 也顶不住!

原创 Lucifer三思而后行 2025-11-28
1111

大家好,这里是公众号 DBA学习之路,分享一些学习数据库路上的知识和经验。

目录

前言

下午有开发同事反馈,一条原本执行时间在 1 秒以内的 SQL 突然延长至 16 秒,严重影响了产线业务的正常运行。经过我分析和优化之后,SQL 恢复正常,数据库性能提升 99.99%。

本文将详细记录整个问题的定位过程、优化方法及相关思考。

问题分析

数据库环境为 Oracle 19C RAC CDB 架构(运行了 6 个 PDB),故障发生时间为 2025.11.27 13:11:09.227

SQL 分析

初步沟通后得知,开发人员通过应用日志监控到某条 SQL 执行时间显著增加,导致接口超时,进而影响业务流程。

首先,通过 SQLID 3jm7s0g3w2px0 获取该 SQL 的 AWR SQL 报告(awrsqrpt)。当然,也可以使用 dbms_xplan.display_cursor 来获取执行计划:

SELECT * FROM TABLE(dbms_xplan.display_cursor('3jm7s0g3w2px0', NULL));

通过 AWR SQL 报告分析,可以发现该 SQL 存在两个执行计划:

慢的执行计划采用了全表扫描方式:

从等待可以看出,SQL 执行时间主要消耗在 I/O 等待上:

快的执行计划则使用了索引访问:

索引访问的 I/O 等待明显减少:

基于经验判断,这很可能是由于执行计划选择错误导致的性能问题,解决方向是固定最优执行计划。

固定执行计划

可以使用 coe_xfr_sql_profile 脚本来固定执行计划:

-- 参数1:SQL_ID,参数2:需要绑定的执行计划哈希值 SQL> @coe_xfr_sql_profile 3jm7s0g3w2px0 1000005031

执行后会在当前目录生成 coe_xfr_sql_profile_3jm7s0g3w2px0_1000005031.sql 脚本,执行该脚本即可完成执行计划绑定:

SQL> @coe_xfr_sql_profile_3jm7s0g3w2px0_1000005031

验证绑定结果:

SQL> SET lines 222 PAGES 1000 COL name FOR a60 COL status FOR a10 COL type FOR a10 SELECT name, status, created, type FROM dba_sql_profiles; NAME STATUS CREATED TYPE ------------------------------------------------------------ ---------- --------------------------------------------------------------------------- ---------- coe_3jm7s0g3w2px0_1000005031 ENABLED 27-NOV-25 03.08.33.103163 PM MANUAL

执行计划绑定后,开发反馈 SQL 执行速度恢复正常,接口不再超时,产线业务得以恢复。

AWR 分析

虽然表面问题已解决,但我进一步采集了 AWR 报告进行深入分析,结果发现了更严重的性能问题。

报告采集时间范围为 60 分钟,DB Time 高达 1,592.57 分钟,平均活动会话数(Avg Active Sessions)达到 23.6,表明数据库在此期间承受了巨大的性能压力:

Load Profile 显示每秒物理读达到 121,964.1 个块,Read I/O 吞吐量为 952.8MB/s,其中直接路径读(Direct Reads)占比超过 96%,达到 934.242M/s

Top Event 中 direct path read 等待事件占比 63.5%,总等待时间 60,694 秒,平均每次等待 35.60 ms,远超 10ms 的健康标准:

Time Model 分析显示 sql execute elapsed time 占 DB Time 的 98.33%,而 DB CPU 仅占 8.43%,进一步证实性能瓶颈主要在 I/O 等待:

进一步分析发现,SQL ID 为 08n0j9b7uw4pv 的语句物理读高达 4.32 亿次,占总量的 98.12%,执行频繁且主要等待事件为直接路径读,表明该 SQL 对大表进行了大量全表扫描操作,是系统最主要的性能瓶颈:

当 Oracle 在执行大表扫描时会自动启用直接路径读机制,以避免污染 Buffer Cache。但当该等待事件占比过高且平均延时超标时,则说明数据库中存在高频执行的大表全表扫描 SQL

这个库的 SQL 得垃圾到什么程度啊,大量全表扫描直接读取磁盘,造成严重 I/O 压力。

该 SQL 的优化方案很简单:为 WHERE 条件中的字段创建联合索引。优化后的执行计划显示将使用索引范围扫描:

------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 33 | 3 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 33 | | | |* 2 | INDEX RANGE SCAN| IDX_XXXXXX_XXX | 1 | 33 | 3 (0)| 00:00:01 | ------------------------------------------------------------------------------------

这个问题也就立刻解决了。

sqlhc 分析

回到最初的问题 SQL,我们使用 sqlhc 工具进行深入分析:

$ sqlplus / as sysdba @sqlhc T '3jm7s0g3w2px0'

分析发现,慢的执行计划平均执行时间为 7.3s,明显比开发说的 16s 要低:

仔细观察可以发现,从 10:00 开始,该执行计划的执行时间从原来的 0.5s 左右激增至 198s 左右,且主要时间都消耗在 I/O 等待上,且 I/O 等待时间呈现逐渐增长趋势:

这表明最初 SQL 的性能下降并非单纯由于多个执行计划,而是受到了系统级 I/O 压力的间接影响。虽然该 SQL 本身存在多个执行计划也是一个问题,但根本原因在于系统中存在大量全表扫描操作导致的 I/O 资源竞争。

开发质疑

我将上述分析结果反馈给开发团队后,我建议优化全表扫描的 SQL,并为其增加合适的联合索引。然而,开发团队对此提出了几点质疑:

  1. SQL 已经创建了索引,为什么优化器选择了全表扫描而非索引访问?
  2. 应用日志明确提示是该 SQL 执行缓慢,应该就是该 SQL 本身的问题,与其他 SQL 无关。
  3. SPC 库的 SQL 性能问题,为何会影响到 MES 库的 SQL 执行?

经过半小时的友好深入沟通,我逐一解释了这些问题:

  • 对于第一点,说明了优化器选择执行计划是基于成本估算的,当统计信息不准确或索引选择性不足时,优化器可能误判成本而选择全表扫描。
  • 对于第二点,解释了在共享资源的数据库环境中,一条高消耗的 SQL 可能影响整个系统的 I/O 性能,进而间接影响其他 SQL 的执行。
  • 对于第三点,阐明了在 RAC CDB 环境中,所有 PDB 库共享存储资源,任何一个数据库的 SQL 导致的 I/O 压力都会影响到整个数据库。

最终,开发团队接受了我的建议。

问题解决

随后,我创建了联合索引之后,晚上抓了一个 AWR 报告看了下数据库性能:

多么健康的数据库,那条 SQL 也早已从 Top SQL 中消失。所以,回到我们最初的标题——“一条烂 SQL 也能拖垮一个数据库!” 这绝不是危言耸听。

写在最后

说实话,这次问题排查给我上了挺生动的一课。刚开始我也以为就是个简单的执行计划跑偏的问题,绑个 profile 就完事了。谁知道越挖越深,最后发现是个“连环案”。

想想也挺有意思的——开发同事看到的是“我的 SQL 怎么突然慢了”,我一开始看到的是“这个 SQL 怎么走错索引了”,但真正的问题却是“整个数据库的 IO 都被打满了”。就像医院里来了个病人说头疼,结果一查是高血压引起的,再一查发现是肾脏出了问题。

最后想说的是,这次问题虽然解决了,但我心里还是有点没底——谁知道下一个“IO 杀手”会什么时候出现呢?或许我们应该趁这个机会,好好梳理一下整个数据库的 SQL 质量了。毕竟,治标不如治本啊。


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

评论