通过pl/sql计算程序的运行时间(r3笔记第77天)

在sqlplus中运行sql语句或者pl/sql的时候如果需要统计运行的时间,只需要开启set timing on选项即可。

SQL> set timing on
SQL> 
SQL> select count(*)from cat;
  COUNT(*)
----------
       408
Elapsed: 00:00:00.15

如果在运行pl/sql的时候如果需要计算程序运行的时间。使用set timing on就显得力不从心了。这个时候可以考虑使用dbms_utility.get_time来得到一个时间戳,然后在程序运行之后再得到一个时间戳,两者想减就是程序的运行时间。

set  serveroutput on
declare
 l_start_time  PLS_INTEGER;
begin
 l_start_time :=  dbms_utility.get_time();
 dbms_output.put_line('this is a  test');
 dbms_lock.sleep(2);   --这里我们尝试使pl/sql块停滞2秒钟
 dbms_output.put_line('Elapsed time  :'||(dbms_utility.get_time-l_start_time)/100);
end;
/

程序运行的结果如下。

this is a test
Elapsed time :2.01
PL/SQL procedure successfully  completed.

但是如果这样计算,可能会出现负数的情况。在pl/sql程序设计这本书中,作者给出的解释是,dbms_utility_get_time得到的数字式从某一个时间点以来所经过的总的毫秒数。而这个数字很大,很可能越界,越界的时候就会从0开始重新开始计数。如果这样计算的话,很可能计算出来的结果就是一个负数了。 我们可以使用如下的pl/sql来做一个改进。

set  serveroutput on
declare
 c_time_gap number:=power(2,32);
 l_start_time  PLS_INTEGER;
begin
 l_start_time :=  dbms_utility.get_time();
 dbms_output.put_line('this is a  test');
 dbms_lock.sleep(2);
 dbms_output.put_line('Elapsed time  :'||mod(dbms_utility.get_time-l_start_time+c_time_gap,c_time_gap)/100);
end;
/

运行结果如下:

this is a test Elapsed time :2

PL/SQL procedure successfully completed. 如果我们在程序中嵌入过多的代码去维护start_time,end_time必然会造成程序的依赖性,如果能够把计算时间的功能独立出来就好了。这样程序的运行不必完全依赖于时间计算,可以灵活的添加和删除。 这种实现在spring的AOP是根据动态代理来实现的,在pl/sql中我们可以使用package来实现。 我们的期望结果就是 begin pro_timing.start_timer; --程序计算起始时间 dbms_output.put_line('this is a test'); --程序业务逻辑 dbms_lock.sleep(2); --程序业务逻辑 pro_timing.show_elapsed('test program'); --程序计算终止时间 end; / 我们可以使用如下的package来实现。

create or replace package pro_timing
authid current_user
is
   procedure start_timer;
  procedure show_elapsed(program_name in  varchar2);
end;
/
create or replace package body pro_timing
is
 c_time_gap  number:=power(2,32);
 l_start_time PLS_INTEGER;
 
 procedure  start_timer
 is 
begin
 l_start_time :=  dbms_utility.get_time();
end;
 procedure show_elapsed(program_name in varchar2)
as 
 l_end_time  varchar2(100);
begin
 l_end_time:=mod(dbms_utility.get_time-l_start_time+c_time_gap,c_time_gap)/100;
dbms_output.put_line(program_name||'  has elapsed time '||l_end_time||'  s.');
end;
end;
/

我们来尝试运行如下的pl/sql块。

begin
 pro_timing.start_timer;
 dbms_output.put_line('this  is a test');
 dbms_lock.sleep(2);
 pro_timing.show_elapsed('test  program');
end;
/

运行结果如下:

this is a test
test program has elapsed time 2 s.
PL/SQL procedure successfully  completed.

这样就基本达到了我们的目标。我们可以在程序中灵活的配置这项功能,对于提升程序的性能来说也是功不可没。

本文分享自微信公众号 - 杨建荣的学习笔记(jianrong-notes)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2014-12-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Netkiller

数据库与图片完美解决方案

数据库与图片完美解决方案 电商商品图品与数据库脏数据完美解决方案 摘要 你是是不是在开发中常常遇到,删除了数据库记录后,发现该记录对应的图片没有删除,或者删除了...

37350
来自专栏数据和云

返璞归真:RAC环境下不同实例的参数文件选择与设置

? 杨廷琨(yangtingkun) 云和恩墨 CTO 高级咨询顾问,Oracle ACE 总监,ITPUB Oracle 数据库管理版版主 参数文件是Or...

34580
来自专栏申龙斌的程序人生

零基础学编程024:如何快速学会SQL?

一位朋友问我如何能够较快地学会SQL,我一时还真不知道如何回答。想学会SQL(结构化查询语言),大概需要理解这些术语:数据库、关系型数据库、面向对象的数据库、键...

54670
来自专栏数据和云

层层升入:SQL极限调优之一次更新操作的N种优化可能

杨廷琨,网名 yangtingkun 云和恩墨技术总监,Oracle ACE Director,ACOUG 核心专家 最近进行了一次更新操作,整个处理和优化的过...

35980
来自专栏Netkiller

MySQL·身份证校验

本文节选自《Netkiller Architect 手札》 4.17. 数据检查 4.17.1. 身份证校验 该函数能够检查身份证号码是否正确 CREATE D...

48750
来自专栏数据和云

按图索骥:Oracle数据库无响应故障的处理思路和方法

熊军(老熊) 云和恩墨西区总经理 Oracle ACED,ACOUG核心会员 无响应故障现象分析 ---- Oracle数据库无响应故障,简单地讲就是数据库实例...

43480
来自专栏数据和云

深入内核:Oracle数据库里SELECT操作Hang解析

崔华,网名 dbsnake Oracle ACE Director,ACOUG 核心专家 编辑手记:感谢崔华授权我们独家转载其精品文章,也欢迎大家向“Oracl...

457100
来自专栏数据和云

追寻完美:数据库SQL优化极致 之 关心隐藏的部分

张中靖 云和恩墨技术专家,软件研发总监 我们先来听一个【老木匠和小木匠的故事】 同样做柜子,老木匠做的是两面光,柜子内外摸起来一样光滑、不扎手;而小木匠做的,大...

35750
来自专栏Netkiller

重新整理AUTO_INCREMENT字段

节选择《Netkiller MySQL 手札》 13.9. 重新整理AUTO_INCREMENT字段 AUTO_INCREMENT 并非按照我们意愿,顺序排列...

36550
来自专栏数据和云

DBA生存警示:误关闭生产库案例及防范建议

编辑手记:对于资深的老DBA们,他们在漫长的职业生涯中养成了很多稀奇古怪的守则,以在复杂多变的环境中“幸存”,这源于无数血泪的教训,我曾经在《数据安全警示录》...

35970

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励