kdv, 04.10.2016
Иногда, в процессе отладки или для других целей, возникает необходимость измерять время выполнения некоторых операций в хранимых процедурах, триггерах или коде execute block.
Попытка использования
CURRENT_TIMESTAMP для отсчетов времени не приводит к успеху. Дело в том, что CURRENT_TIMESTAMP в блоке кода вычисляется только один раз, и повторные обращения к CURRENT_TIMESTAMP будут выдавать то же самое время. Пример
time_start = CURRENT_TIMESTAMP(3);
-- длительная операция
time_end = CURRENT_TIMESTAMP(3);
time_diff = :time_end - :time_start;
в результате в time_diff будет всегда 0.
Кстати, иногда, по привычке, вместо простого присвоения переменной значения функции пишут код вида
select CURRENT_TIMESTAMP(3) from rdb$database into :time_end;
В этом нет никакой необходимости, и это даже вредно, т.к. select приводит к лишнему чтению с диска или из кэша. Спасает тут лишь то, что в rdb$database только одна запись, располагающаяся на 1 странице БД.
Вместо CURRENT_TIMESTAMP необходимо использовать CAST('now' as TIMESTAMP). Такой вызов всегда будет возвращать текущее время.
Вот рабочий пример
create or alter procedure B
returns (
TIME_DIFF varchar(256))
as
declare variable TIME_START timestamp;
declare variable TIME_END timestamp;
declare variable I integer;
begin
time_start=cast('now' as timestamp);
-- длительная операция
select count(*) from employee e1, employee e2, employee e3 into :i;
time_end=cast('now' as timestamp);
time_diff = cast(datediff(millisecond, cast(:time_start as timestamp),
cast (time_end as timestamp)) as varchar(56));
suspend;
end
Результат можно увидеть выполнив запрос SELECT * FROM B.
Чтобы получить хоть какую-то заметную разницу, используется count на перемножении таблицы employee - 42 записи превращаются в 74088, что дает интервал времени около 36 миллисекунд.
p.s. если хотите убедиться в том, что CURRENT_TIMESTAMP работает именно так - замените CAST('now' as timestamp) на CURRENT_TIMESTAMP. В результате time_start и time_end будут одинаковыми, и процедура вернет 0.