当前位置:首页 > 问答 > 正文

怎么快速简单地搞定Oracle语句执行时间的记录问题

最直接也最不需要额外工具的方法就是利用SQLPlus或者SQL Developer等工具的内置计时功能,这个方法几乎不需要任何学习成本,适合临时查看单条语句的性能,在SQLPlus中,你可以在执行SQL语句之前输入SET TIMING ON,然后当你运行任何SQL语句(比如一个简单的SELECT * FROM your_table WHERE ...)后,工具会自动在结果下方显示该语句执行所耗费的时间,通常会精确到百分秒,在Oracle SQL Developer中,这个功能是默认开启的,你运行完查询后,在下面的“脚本输出”或“查询结果”窗口附近,直接就能看到“已用时间”的提示,这种方法的好处是直截了当,缺点是你需要手动记录这个时间,如果想把多次执行的时间进行对比或者做分析,就比较麻烦,来源依据是Oracle官方文档中关于SQL*Plus命令的说明。

怎么快速简单地搞定Oracle语句执行时间的记录问题

如果你觉得手动记录不方便,想要一个更自动化、能记录更多信息(而不仅仅是时间)的方法,那么使用Oracle自带的内置视图V$SQL是一个强大且仍然相对简单的选择,数据库本身就会把所有执行过的SQL语句的相关信息缓存起来,放在这个视图中,你可以像查询普通表一样去查询它,这里面的信息非常丰富,包括SQL语句的文本片段、执行次数、消耗的CPU时间、磁盘读取次数(物理读)、缓冲区读取次数(逻辑读)以及最重要的—— elapsed_time(总耗时)。

举个例子,你想知道你刚才执行的那条慢SQL到底花了多少时间,你可以这样查: SELECT sql_text, elapsed_time, cpu_time, disk_reads, buffer_gets FROM V$SQL WHERE sql_text LIKE '%你的SQL关键字%'; 你需要把你的SQL关键字替换成你执行的SQL语句里一段独特且容易识别的字符串,查询结果中的elapsed_time单位是微秒,你需要除以1000000才能得到秒,这种方法的好处是,数据是数据库自动收集的,你可以在语句执行后的任何方便的时间去查询,而且还能看到CPU、IO等其他性能指标,帮助你判断时间到底花在了哪里,缺点是,如果数据库非常繁忙,你刚才执行的SQL可能很快就被挤出共享池(缓存),导致你在V$SQL里找不到了,来源依据是Oracle官方文档中关于性能动态视图的章节。

怎么快速简单地搞定Oracle语句执行时间的记录问题

对于需要长期、系统性地监控特定语句或应用场景的执行时间,上面两种方法就显得有些力不从心了,这时,一个快速搭建的“日志表”方案会非常实用,这个方法的思路就是“自己动手,丰衣足食”,你只需要创建一个非常简单的数据表,专门用来存放执行记录,这个表通常只需要几个字段就够了,一个自增的主键ID、记录时间的戳字段、执行的SQL语句文本、以及执行耗时。

你可以在你关注的SQL语句前后,加上插入日志的语句,最朴素的做法是,在SQL执行前获取一次系统时间,执行后再获取一次,计算差值,然后插入日志表,在Oracle里,你可以用DBMS_UTILITY.GET_TIME这个函数来获取精确的时间点(单位是百分之一秒,但精度更高),具体操作可以是这样:

  1. 先声明几个变量,比如v_start_time NUMBER;v_end_time NUMBER;
  2. 在执行目标SQL前,写v_start_time := DBMS_UTILITY.GET_TIME;
  3. 接着执行你的业务SQL语句。
  4. 执行完后,写v_end_time := DBMS_UTILITY.GET_TIME;
  5. 计算耗时并插入日志表:INSERT INTO your_log_table (log_time, sql_text, duration) VALUES (SYSDATE, '你的SQL语句描述', (v_end_time - v_start_time)/100);,这里除以100是把单位从百分秒转换为秒。

你可以把这一套逻辑写成一个存储过程,这样每次调用起来就更方便,这个方案的优势在于完全可控,你可以记录任何你想记录的信息,并且所有历史数据都保存在你自己的表里,随时可以查询、分析、生成图表,这对于开发阶段性能调优或者监控核心业务的数据库操作非常有用,缺点是需要在业务代码中嵌入额外的逻辑,有一定的侵入性,来源依据是Oracle官方文档中关于DBMS_UTILITY包的说明。

如果你的环境允许使用一些外部工具,那么像Oracle SQL Developer这样的图形化工具本身就提供了更强大的监控功能,它的“监视数据库活动”功能可以实时看到当前正在执行的SQL及其耗时;它的“SQL跟踪”功能可以生成非常详细的执行报告,里面包含了执行计划每一个步骤的时间消耗,这些工具虽然功能强大,但可能需要一些配置,并且更适合DBA进行深度的性能诊断,对于“快速简单”这个首要目标来说,可能稍显重量级。

如果你只是偶尔看一眼时间,用工具自带的SET TIMING ON最快,如果你想事后分析且SQL不太会被挤出缓存,查V$SQL视图很方便,如果你需要长期、定制化地记录和分析,那么自己建一个日志表是最灵活实用的方法,你可以根据你的具体需求和场景,选择最适合你的那一种。

怎么快速简单地搞定Oracle语句执行时间的记录问题