Измерение времени в хранимых процедурах, триггерах и execute block

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.

Подпишитесь на новости Firebird в России

Подписаться