测量plsql过程中sql语句的时间

Posted

技术标签:

【中文标题】测量plsql过程中sql语句的时间【英文标题】:measure time of an sql statement in a procedure in plsql 【发布时间】:2012-02-14 22:13:58 【问题描述】:

我必须编写一个程序来节省表中任何 sql 语句的执行时间。

程序由exec measuresqltime('sql statement as string');调用

我的想法是这样的:

  --declarations 
  timestart NUMBER;
  BEGIN 
    dbms_output.enable; 
    timestart:=dbms_utility.get_time(); 
    EXECUTE IMMEDIATE sql
    COMMIT; 
    dbms_output.put_line(dbms_utility.get_time()-timestart); 
    -- save time

但它不适用于SELECT *... 子句。 (我认为sql需要一个INTO-order)

有没有办法在过程中执行任何 sql 语句?

【问题讨论】:

【参考方案1】:

如果您的 SQL 语句是 SELECT,您需要从游标中获取数据,以便对其执行时间进行有意义的测量。

如果您不从游标中获取,则仅测量在“解析”和“执行”阶段花费的时间,而大部分工作通常在 SELECT 语句的“获取”阶段完成。

如果您不知道实际语句的列数,您将无法使用EXECUTE IMMEDIATEOPEN cursor FOR 'string' 获取。如果 SELECT 的列数/类型未知,则必须使用动态 SQL 包 DBMS_SQL

这是一个例子:

SQL> CREATE OR REPLACE PROCEDURE demo(p_sql IN VARCHAR2) AS
  2     l_cursor  INTEGER;
  3     l_dummy   NUMBER;
  4     timestart NUMBER;
  5  BEGIN
  6     dbms_output.enable;
  7     timestart := dbms_utility.get_time();
  8     l_cursor  := dbms_sql.open_cursor;
  9     dbms_sql.parse(l_cursor, p_sql, dbms_sql.native);
 10     l_dummy := dbms_sql.execute(l_cursor);
 11     LOOP
 12        EXIT WHEN dbms_sql.fetch_rows(l_cursor) <= 0;
 13     END LOOP;
 14     dbms_sql.close_cursor(l_cursor);
 15     dbms_output.put_line(dbms_utility.get_time() - timestart);
 16  END;
 17  /

Procedure created.

SQL> exec demo('SELECT * FROM dual CONNECT BY LEVEL <= 1e6');
744

PL/SQL procedure successfully completed.

请注意,这将测量提取到 SELECT 的最后一行所需的时间。

【讨论】:

嘿,这看起来很棒:) 但它只适用于 fpr select 语句,不是吗?是否有运行删除或插入语句的选项? @sheepy:您无法获取 DML 游标(INSERT/UPDATE...),因此第 12 行将在这种情况下引发错误。捕获异常,该过程将适用于 DML 和 SELECT 查询。 dbms_utility.get_time 不可信,您应该使用 systimestamp 代替,请参阅asktom.oracle.com/pls/asktom/… @Superdooperhero 这根本不是 Tom Kyte 的建议!他建议用SYSTIMESTAMP 替换SYSDATE 以获得更高的精度。他仍然使用dbms_utility.get_time in his suggested code :)【参考方案2】:

计算执行时间的持续时间

PROCEDURE MY_PROCEDURE IS
  timeStart  TIMESTAMP;
  timeEnd    TIMESTAMP;
BEGIN
  timeStart  := SYSTIMESTAMP;

  -- YOUR CODE HERE

  timeEnd    := SYSTIMESTAMP;

  INSERT INTO PROC_RUNTIMES (PROC_NAME, START_TIME, END_TIME)
    VALUES ('MY_PROCEDURE ', timeStart  , timeEnd    );
END MY_PROC;

【讨论】:

【参考方案3】:

完成 devosJava 回答...避免在黎明时使用它;P

PROCEDURE MY_PROCEDURE IS
  timeStart  TIMESTAMP;
  timeEnd    TIMESTAMP;
  timeSecond NUMBER
BEGIN
  timeStart  := SYSTIMESTAMP;

  -- YOUR CODE HERE

  timeEnd    := SYSTIMESTAMP;
  timeSecond :=((extract(hour from timeEnd)*3600)+(extract(minute from timeEnd)*60)+extract(second from timeEnd))-((extract(hour from timeStart)*3600)+(extract(minute from timeStart)*60)+extract(second from timeStart));
  dbms_output.put_line('finished: '||timeSecond||' seconds');
END MY_PROC;

【讨论】:

timeSecond := extract(second from timeEnd - timeStart);【参考方案4】:

INSERT INTO PROC_RUNTIMES(PROC_NAME,START_TIME,END_TIME) 值('PROC_NAME',TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'),NULL );

您的查询在这里;

INSERT INTO PROC_RUNTIMES(PROC_NAME,START_TIME,END_TIME) 值('PROC_NAME',NULL,TO_CHAR (SYSDATE, 'DD/MM/YYYY HH24:MI:SS'));

【讨论】:

以上是关于测量plsql过程中sql语句的时间的主要内容,如果未能解决你的问题,请参考以下文章

oracle怎样跟踪一条sql语句的执行过程?

plsqldeveloper如何检索sql语句在哪些存储过程

PL SQL - 使用动态 SQL 生成删除语句

Oracle [存储过程] 执行动态拼接SQL语句并返回结果??

SQL语句执行过程详解

关于plsql!!!