Если ваш оператор 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.
эй, это выглядит великолепно :), но он работает только с предложениями выбора fpr, не так ли? Есть ли опция o run delete или insert-statements? – sheepy
@sheepy: Вы не можете получить курсор DML (INSERT/UPDATE ...), поэтому строка 12 вызовет ошибку в этом случае. Поймайте исключение, и процедура будет работать как для запросов DML, так и для SELECT. –