在 Oracle 数据库中,SQL 语句的执行性能是开发者和 DBA 关注的焦点。通过监控工具如 SQL Monitor ,OEM或 AWR 报告,我们可以获取各种时间指标,如 Duration Time、Elapsed Time、CPU Time 和 IO Time 等。这些指标帮助我们诊断瓶颈、优化查询,并理解客户端与数据库交互的影响。 但是你们知道这些时间分别代表什么吗?先看一个sql monitor的截图

一、Oracle SQL 执行时间指标概述
Oracle 在执行 SQL 时,会记录多个时间维度,这些指标反映了从查询解析到结果返回的全过程。以下是核心指标的解释:
- Elapsed Time:
- 定义:SQL 语句从开始执行到完成(包括所有子过程)的总实际时间,通常以秒为单位。
- 包含内容:CPU 时间、IO 等待、网络延迟、锁等待等所有消耗。
- 意义:这是用户感知的最直接性能指标。如果 Elapsed Time 过长,可能表示查询效率低或资源争用。
- CPU Time(CPU 时间):
- 定义:SQL 执行过程中 CPU 实际使用的处理时间,不包括等待时间。
- 包含内容:解析、优化、数据计算等 CPU 密集型操作。
- 意义:如果 CPU Time 接近 Elapsed Time,说明查询是 CPU 绑定的(计算密集);反之,则可能是 IO 或其他等待主导。
- 示例:图 中 CPU Time 为 5.86 秒,占 Elapsed Time 的绝大部分(约 81%),表明这个 SQL 主要是计算密集型,而非 IO 瓶颈。
- IO Time(IO 等待时间):
- 定义:SQL 执行中等待磁盘或存储 IO 操作的时间,通常体现在 IO Waits(IO 等待秒数)中。
- 包含内容:读取数据块(Buffer Gets)、物理读(Read Reqs 和 Read Bytes)等。
- 意义:高 IO Time 往往表示数据访问效率低,可能需要优化索引、增加缓存或调整存储配置。
- 示例:图中显示 IO Waits 为 1.36 秒,Read Reqs 1493 次,Read Bytes 886MB。这意味着 SQL 需要从磁盘读取大量数据(近 1GB),IO 等待贡献了部分 Elapsed Time。
- Duration Time(持续时间):
- 定义:从客户端发起 SQL 到接收完整结果的总时间,包括数据库执行时间和客户端处理时间(如 Fetch 操作)。
- 包含内容:Elapsed Time 加上客户端的网络传输、结果集缓冲和多次 Fetch 的开销。
- 意义:Duration 通常大于或等于 Elapsed Time,因为它涵盖了端到端的体验。如果差距大,可能是客户端配置问题。
- 示例:图中显示 Duration 为 27 秒,而 Elapsed Time 仅 7.22秒,相差近 20秒。这很可能由于多次 Fetch Calls 导致的客户端延迟,我们将在下一节详细讨论。
其他相关指标:
- Fetch Calls(获取调用次数):客户端从数据库拉取结果集的次数。如果结果集大,而 Fetch Size 小,则需要多次调用,增加网络开销。
- Buffer Gets(缓冲区获取):逻辑读次数,高值表示内存访问频繁。
- 示例:图中显示 Fetch Calls 高达 111K,Buffer Gets 114K,这表示结果集很大,客户端分批拉取数据。
二、Fetch Calls 的影响
Java 默认 10 的陷阱与结果集输出问题在 Oracle SQL 执行中,Fetch Calls 是性能杀手之一,尤其在处理大结果集时。客户端(如 Java 应用)不会一次性拉取所有行,而是分批(Batch)获取,这由 Fetch Size 参数控制。
- Fetch Calls 的工作原理:
- Oracle 数据库执行 SQL 后,结果集存储在游标中。客户端通过 OCI(Oracle Call Interface)或 JDBC 等接口调用 Fetch 来获取行。
- 每次 Fetch 调用返回一批行(Fetch Size 指定的大小),直到结果集耗尽。
- 高 Fetch Calls 表示多次网络往返,增加延迟,尤其在高延迟网络环境中。
- Java 默认 Fetch Size = 10 的问题:
- 时间膨胀:每个 Fetch 都有网络开销、上下文切换和缓冲管理,导致 Duration >> Elapsed Time。
- 资源消耗:数据库端需保持游标开放更久,消耗内存;客户端 CPU 和网络负载增加。
- 结果集输出延迟:用户感知上,结果显示缓慢,甚至应用卡顿。
- 在 JDBC 中,默认 Fetch Size 为 10,即每次只拉取 10 行。这适合小结果集,但对于大查询(如返回数万行),会导致成千上万的 Fetch Calls。
- 影响:当然这个是一个极端的特例,这个sql的结果集超过110万,这是完全不合理的。 应该从业务端进行改善。
- 优化建议:
- 将 JDBC Fetch Size 增大(如 setFetchSize(1000)),减少 Calls 次数。但需平衡内存使用,避免 OOM。
- 使用批量处理或游标优化(如 PL/SQL 中的 BULK COLLECT)。
- 如果是报告类查询,考虑分页或服务器端聚合,减少返回行数。
- 监控:使用 V$SQL_MONITOR 或 AWR 报告追踪 Fetch 指标。
三、 SQL 时间问题的常见场景与解决方案
基于以上指标和截图,我们梳理一些典型的 SQL 时间问题:
- Elapsed Time 高,但 CPU Time 低:
- 原因:IO 瓶颈(如 Image 0 的 1.36s IO Waits),或锁/队列等待。
- 解决方案:添加索引、优化存储(ASM/SSD)、使用 materialized views。
- Duration >> Elapsed Time:
- 原因:客户端 Fetch 开销大(如图中案例,27s vs 7s),网络延迟,或应用层处理慢。
- 解决方案:增大 Fetch Size,优化网络,或使用阵列 Fetch(Array Fetch)。
- 高 Fetch Calls 导致的整体性能衰退:
- 原因:结果集过大 + 小 Fetch Size(如 Java 默认 10)。
- 解决方案:如上所述;另外,评估是否需要全结果集——或许用 COUNT(*) 先检查行数。
- 执行时间变异性:
- 如 Image 1 的柱状图,不同执行从 19s 到 30s。
- 原因:数据量变化、计划变更(CBO 优化器)、并发负载。
- 解决方案:绑定变量、固定执行计划(Outline)、监控统计信息。
- 其他指标异常:
- 高 Buffer Gets(114K):表示逻辑 IO 多,需优化 SQL(如避免全表扫描)。
- 高 Read Bytes(980MB):物理 IO 重,考虑增加 SGA/PGA。
结语Oracle SQL 的时间指标如 Elapsed Time、CPU Time 和 Duration 提供了多维度视角,帮助我们从数据库到客户端全面优化性能。 只有了解每个参数的含义,才能更好的去理解sql去优化sql。

3872

被折叠的 条评论
为什么被折叠?



