Базовая установка PostgreSQL не даёт нам информацию об активности работы наших функций так как мониторинг выключен. Мониторинг требует фиксации данных, а это всегда небольшая дополнительная нагрузка на систему. Зачем нагружать то, что хорошо работает (до поры, до времени). И всё же, как посмотреть/активировать статистику работы своих функций?
Сперва проверяем результат значения конфигурационного параметра «track_functions«.
show track_functions;

В случае по умолчанию, мы получим значение «none«. Оно говорит нам о том, что сбор статистики по функциям отключён в PostgreSQL. И в этом можно убедиться, если обратиться к системному представлению «pg_stat_user_functions«.
select * from pg_stat_user_functions;
Результатом будет пустая таблица.

Возможные варианты значений параметра «track_functions«:
- none
- pl
- all
Если все функции написаны на языке «plpgsql» (на процедурном языке), то достаточно установить значение «pl«.
Если нужна статистика по всем вызовам функций включая языки «SQL» и «C», то устанавливаем значение «all«.
Как работать с параметром «track_functions» в PostgreSQL?
Важно! Тут есть несколько решений для отслеживания (зависит от задачи):
- Мы следим только за конкретными функциями и в телах этих функций локально меняем параметр «track_functions»
- Мы устанавливаем параметр «track_functions» только в рамках открытого соединения (вкладки) для клиентских программ на подобии DBeaver.
- Мы устанавливаем параметр «track_functions» глобально в конфигурационном файле СУБД PostgreSQL
Рассмотрим отслеживание конкретной функции и в её теле установим значение «all» для параметра «track_functions«. Вызываем эту команду сразу после блока begin.
set local track_functions = 'all';
После этого должна накопиться статистика по вызовам вложенных функций, чтобы мы смогли увидеть записи в «pg_stat_user_functions«.

Внимание! Подвох такого подхода в том, что фактически в статистку начнёт попадать только информация по всем вложенным вызовам функций. А та функция, внутрь которой мы поместили отслеживание, не будет отражена в системном представлении.
В чём плюс такого отслеживания? Мы можем точечно отследить узкие места в работе нашей сложной функции так как будем понимать какая вложенная функция медленнее всего отрабатывает.
Поле «calls» говорит нам о том, сколько раз вызывалась функция с момента отслеживания.
Поле «total_time» говорит нам о том, сколько общего времени было потрачено на выполнение этой функции и всех других функций, вызванных ею, в миллисекундах с момента отслеживания.
Поле «self_time» говорит нам о том, сколько общего времени было потрачено на выполнение самой функции, без учёта других функций, которые были ею вызваны, в миллисекундах с момента отслеживания.
Если поля «total_time» и «self_time» равны, это значит что данные функции не вызывали никого внутри себя — не вызывали другие самописные функции! Это значит, что внутри них есть только базовая логика SQL.
Можно немного дополнить данные системного представления и получить суммарную статистику по вложенным функциям.
select *, sum(calls) over() as x_calls, sum(total_time) over() as x_total_time, sum(self_time) over() as x_self_time, sum(total_time) over() / sum(calls) over() as x_avg_total_one_call_time_ms, sum(self_time) over() / sum(calls) over() as x_avg_self_one_call_time_ms from pg_stat_user_functions;
Мы добавили средние значения для существующих полей

Функция, которую мы отслеживаем, каждый раз вызывает по 6 функций и иногда затрагивает ещё 3 функции. При накопленной статистике мы можем оценить среднее время роботы нашей функции.
На 213449 её вызовов мы суммарно вызвали 1283178 других вложенных вызовов. Общее время составило 268659 миллисекунд (268 секунд).
Итого: наша функция работает в среднем 1,259 миллисекунд (268659 / 213449).
Этой цифре вполне можно доверять так как внутри неё самой мало сложных запросов в БД. Все сложные запросы и проверки делегированы на вложенные функции. По сути длительность их работы и есть работа нашей отслеживаемой функции.