2012-01-20 21 views
5

Debo escribir un procedimiento que guarde el tiempo de ejecución de cualquier instrucción sql en una tabla.medir el tiempo de una instrucción sql en un procedimiento en plsql

El procedimiento está llamando por exec measuresqltime('sql statement as string');

Mi idea es la siguiente:

--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 

Pero no funcionó para mí por una cláusula SELECT *.... (Creo que sql necesita un INTO-orden)

¿Hay alguna manera de ejecutar cualquier sql-atatements en un procedimiento?

Respuesta

13

Si su instrucción de SQL es SELECCIONAR, debe buscar desde el cursor para tener una medida significativa de su tiempo de ejecución.

Si no obtiene del cursor, solo mide el tiempo empleado en las fases de "análisis" y "ejecución", mientras que gran parte del trabajo se realiza generalmente en la fase "captar" para las instrucciones SELECT.

No podrá buscar con EXECUTE IMMEDIATE o OPEN cursor FOR 'string' si no sabe la cantidad de columnas que tendrá la declaración real. Deberá utilizar el paquete de SQL dinámico DBMS_SQL si se desconoce el número/tipo de columnas de SELECT.

He aquí un ejemplo:

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. 

Tenga en cuenta que esto será medir el tiempo necesario para traer a la última fila de la SELECT.

+0

hey, que se ve genial :) pero solo funciona para las declaraciones de selección ¿no? ¿Hay una opción o ejecutar delete o insert-statements? – sheepy

+0

@sheepy: No se puede obtener un cursor DML (INSERT/UPDATE ...) por lo que la línea 12 generará un error en ese caso. Captura la excepción y el procedimiento funcionará para las consultas DML y SELECT. –

1

Para calcular la duración de un tiempo de ejecución

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

completar devosJava contestado ... evitar su uso en la madrugada; 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; 
+2

'timeSecond: = extract (second from timeEnd - timeStart);' – Roland

0

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

Su consulta aquí;

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

Cuestiones relacionadas