如何测试PLSQL性能_DBMS_UTILITY.GET_TIME毫秒级耗时计算
DBMS_UTILITY.GET_TIME 返回的是百分之一秒,不是毫秒
不少朋友在调试PL/SQL性能时,都踩过这个坑:想用dbms_utility.get_time来测量毫秒级耗时,结果发现两次调用相减的结果总是整数,数值跳变明显,甚至偶尔还会出现负数。这到底是怎么回事?其实,问题出在对这个函数返回单位的理解上。它返回的并非毫秒,而是「自数据库实例启动以来的百分之一秒(centisecond)」,也就是以10毫秒为单位的计数值。所以,它的最小分辨率就是10ms,而不是我们通常期望的1ms。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

这意味着什么呢?简单来说,如果你的代码执行时间小于10毫秒,GET_TIME很可能返回相同的值,相减结果就是零。如果执行时间落在10到19毫秒之间,它只会显示1;20到29毫秒则显示2……本质上,它是向下取整到最近的10毫秒倍数。因此,有几点需要特别注意:
- 别用它来测量单条SQL或极短的PL/SQL代码块,误差会大到失去参考意义。
- 它更适合粗粒度的对比,比如评估两个存储过程的整体耗时差异是否超过了数十毫秒。
- 跨会话调用时要小心,虽然不同会话看到的时间基准一致,但系统时钟漂移或实例重启都会影响返回的绝对值。
正确计算耗时的写法:相减后乘 10 得到毫秒近似值
虽然无法获得精确的毫秒值,但只要理解了单位,进行合理换算就能得到可用的近似值。这里的关键,与其说是“怎么转换成毫秒”,不如说是“如何避免除法优先级导致的截断错误”和“怎样规避会话状态带来的干扰”。
一个典型的错误写法是:elapsed := end_time - start_time / 100;。这里由于除法优先级更高,会导致计算结果完全错乱。
- 正确的做法是必须先做减法,再乘以10:
elapsed_ms := (end_time - start_time) * 10; - 变量类型推荐使用
NUMBER或PLS_INTEGER,以避免隐式转换可能带来的精度损失。 - 如果想得到更易读的整数结果,可以四舍五入:
ROUND((end_time - start_time) * 10)。 - 需要牢记的是,这样计算出的值仍是近似值,实际误差范围在±5毫秒左右。
比 GET_TIME 更准的替代方案:DBMS_PROFILER 或 DBMS_SESSION
当真正需要定位毫秒级瓶颈时——比如想知道函数内部某一段逻辑具体卡在哪里——DBMS_UTILITY.GET_TIME就显得力不从心了。好在Oracle自带了一些更可靠的分析工具。
DBMS_PROFILER可以逐行统计代码的执行次数和耗时,不过需要经过开启、收集数据、分析结果三个步骤。- 可以用
DBMS_SESSION.SLEEP(0.01)配合GET_TIME来验证时间单位是否生效(注意,SLEEP操作不要在生产环境随意使用)。 - 对于Oracle 12c及以上的版本,推荐使用
DBMS_MONITOR结合ASH(Active Session History)数据,查询V$ACTIVE_SESSION_HISTORY视图中的TIME_WAITED字段,其单位是微秒,精度更高。 - 如果只是简单的脚本调试,其实不如直接使用SQL*Plus的
SET TIMING ON命令,它的底层调用了精度更高的计时器。
容易被忽略的陷阱:时区、RAC 节点、自治事务干扰
看起来只是一个简单的减法运算,但背后其实藏着几个容易踩中的隐蔽雷区。
- 在RAC(Real Application Clusters)环境下,不同节点的
GET_TIME基准时间可能存在微小偏差,因此跨节点进行计时比较并不建议。 - 在自治事务(
AUTONOMOUS_TRANSACTION)中调用GET_TIME,其返回值仍然遵循父会话的时间线,并不会为自治事务提供独立的计时。 - 数据库时间受操作系统时钟影响;如果数据库主机进行了NTP时间校正,
GET_TIME的返回值可能出现突变(虽然不常见,但在设置监控告警时需要留意)。 - 不要在循环中高频调用它——这个函数本身也有开销,频繁调用反而会扭曲被测代码的真实耗时。
说到底,要进行真正的性能压测或深度调优,必须结合AWR报告来分析DB Time和SQL执行计划,而不能仅仅依赖几个GET_TIME的测量点去猜测性能瓶颈所在。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
SQL如何调试复杂的嵌套查询_利用EXPLAIN分析执行路径
SQL如何调试复杂的嵌套查询:利用EXPLAIN分析执行路径 调试复杂SQL,尤其是嵌套查询,最怕的就是面对执行计划一头雾水。其实,读懂EXPLAIN的输出,关键在于理解优化器背后的权衡逻辑,而不是死记硬背几个术语。下面这几个常见的执行计划“疑点”,就是很好的切入点。 EXPLAIN 看不懂执行计划
mysql如何将时间戳转为日期_使用from unix time函数转换
MySQL中FROM_UNIXTIME()转换时间戳需注意时区、引号、NULL及类型溢出 在MySQL数据库操作中,将时间戳转换为可读日期是常见需求,FROM_UNIXTIME()函数是实现这一功能的核心工具。然而,实际应用中存在四个关键细节极易被忽视,直接影响数据准确性:必须使用 +08:00 格
mysql如何将表定义转化为JSON格式_数据库结构文档化技巧
MySQL表结构转JSON:避开常见陷阱,实现高效文档化方案 你是否需要将MySQL的表定义转换为一份清晰、可直接使用的JSON文档?这项工作听起来简单,但实际操作中,直接解析SHOW CREATE TABLE命令的输出会遇到格式不统一的问题,容易出错。有没有更稳定可靠的方法?答案是肯定的。 利用
SQL如何高效合并两个结构相似的表_使用UNION_ALL代替不必要的JOIN
SQL如何高效合并两个结构相似的表:使用UNION ALL代替不必要的JOIN 想把两个结构相似的表合并起来,你首先想到的是不是JOIN?其实,在很多场景下,UNION ALL才是那个更直接、更高效的选择。关键在于,你得先搞清楚自己的目标:是要把数据“纵向堆叠”起来,还是要“横向关联”起来。前者是U
mysql如何定期清理过期测试数据_mysql数据生命周期管理
MySQL测试数据清理:从“能删”到“会删”的四个关键步骤 清理数据库中的过期测试数据,看似是一项基础的运维任务,实则蕴含着诸多技术细节与风险考量。直接执行DELETE语句固然简单,但如何高效、安全、可控地完成清理,才是衡量专业度的关键。 用 DELETE + WHERE 清理过期测试数据最直接,但
- 日榜
- 周榜
- 月榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

