2012-01-20 2 views
5

Я должен написать процедуру, которая сохраняет время выполнения любого sql-оператора в таблице.измерять время sql-инструкции в процедуре в plsql

Процедура вызова по 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-заказ)

Есть ли способ выполнить любые транзакции sql в процедуре?

ответ

13

Если ваш оператор SQL является SELECT, вам нужно извлечь из него курсор, чтобы иметь значимую меру его времени выполнения.

Если вы не извлекаете из курсора, вы измеряете время, затрачиваемое на фазы «разбора» и «выполнение», тогда как большая часть работы обычно выполняется на этапе «выборки» для операторов SELECT.

Вы не сможете получить с помощью EXECUTE IMMEDIATE или OPEN cursor FOR 'string', если вы не знаете количество столбцов, которое имеет фактический оператор. Вам нужно будет использовать динамический пакет SQL DBMS_SQL, если число или тип столбцов SELECT неизвестно.

Вот пример:

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.

+0

эй, это выглядит великолепно :), но он работает только с предложениями выбора fpr, не так ли? Есть ли опция o run delete или insert-statements? – sheepy

+0

@sheepy: Вы не можете получить курсор DML (INSERT/UPDATE ...), поэтому строка 12 вызовет ошибку в этом случае. Поймайте исключение, и процедура будет работать как для запросов DML, так и для SELECT. –

1

Для расчета продолжительности в течение времени выполнения

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; 
+2

'timeSecond: = extract (секунда от timeEnd - timeStart);' – Roland

0

INSERT INTO PROC_RUNTIMES (proc_name, START_TIME, END_TIME) VALUES ('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, 'ДД/ММ/ГГГГ HH24: MI: SS'));

Смежные вопросы