Профилирование долгих запросов
Данная функциональность позволяет отслеживать состояние выполнения запроса не дожидаясь его окончание. Стоит учитывать, что включение профилирования привносит некоторое количество накладных расходов для всех запросов бэкенда.
Подготовка
Для включения профилирования необходимо установить параметр query_profiling
в настройках (либо в конфигурационном файле, либо динамически с помощью команды SET
).
Для профилирования также необходима функционирующая очередь сообщений, в частности вызов select start_mq_broker();
. Далее всё взаимодействие происходит с системными очередями, которые уже созданы.
Анализ информации очень чувствителен к статической информации поддерживаемой СУБД, поэтому рекомендуется использовать ANALYZE для исследуемых таблиц.
Анализ информации.
Для получения информации о выполнении запроса модуль предоставляет 2 основные функции:
- qhb_running_queries
- qhb_dump_qep
Функция qhb_running_queries
возвращает временную таблицу, которая содержит следующую информацию:
Название колонки | Тип | Описание | Комментарий |
---|---|---|---|
query_id | int8 | Уникальный идентификатор запроса | |
backend_pid | int8 | pid postgres-бэкенда, на котором выполняется запрос | Эквивалентен значению из pg_stat_activity.pid |
query_string | text | Текстовая строка запроса | |
query_started | timestamptz | Время начала работы запроса | |
ETC | timestamptz | Ориентировочное время окончания работы | Может быть NULL, при сложных запросах оценка может быть далека от реальности |
elapsed_counter | float8 | Внутренний счетчик для отслеживания выполненной работы запроса | |
estimated_total_counter | float8 | Внутреннее ожидаемое количество работы для запроса |
Функция qhb_dump_qep
принимает идентификатор запроса из qhb_running_queries
и отображает дерево плана запроса (query execution plan). Второй аргумент принимает строку со способом форматирования:
'full'
— отображает полные значения счетчиков;'scaled'
— отображает значения счетчиков приведенные к одному порядку (отображается в поле units);'scientific'
— отображает значения счетчиков;'percent'
— отображает значения счетчиков в процентах;'mixed_percent'
— отображает значения счетчиков в процентах и абсолютное ожидаемое значение;
Функция возвращает дерево плана, эквивалентное тому, что возвращает EXPLAIN, а также статус выполнения для каждого узла. Стоит иметь ввиду, что узлы могут иметь прогресс в 100%, но тем не менее вызываться повторно увеличивая счетчик циклов (loops). Пример анализа запроса:
# select start_mq_broker();
start_mq_broker
-----------------
(1 row)
# create table tb (x int);
CREATE TABLE
# insert into tb select generate_series(1, 50000);
INSERT 0 50000
# select a.x, count(*) from tb a, tb b group by a.x;
В другом клиенте:
# select * from qhb_running_queries();
query_id | backend_pid | query_string | query_started | ETC | elapsed_counter | estimated_total_counter
----------+-------------+----------------------------------------------------+-------------------------------+-------------------------------+--------------------+-------------------------
7 | 1064 | select a.x, count(*) from tb a, tb b group by a.x; | 2022-02-10 16:34:01.719477+03 | 2022-02-10 16:46:49.189314+03 | 2337060.9605833497 | 97739647.85
(1 row)
# select qhb_dump_qep(query_id, 'percent') from qhb_running_queries() where query_string like 'select a.x%';
qhb_dump_qep
-------------------------------------------------
+
~ Agg (progress: 0.00%, loops: 0) +
~ Nest Loop (progress: 5.69%, loops: 0) +
-> Seq Scan (progress: 6.45%, loops: 0) +
~ Material (progress: 88.30%, loops: 3648)+
~ Seq Scan (progress: 88.32%, loops: 0)+
(1 row)
Ограничения
Реализация в текущем виде содержит ограничения:
- Память для внутренних структур профилирования фиксирована и ограничена 8 МиБ, при превышении данного значения, профилирование будет игнорироваться.
- Значение
ETC
предсказывается интерполяцией всего по двум точкам во времени, это означает, что это значение может достаточно сильно колебаться с течением времени. - Для анализа работы запроса используются оценки затрат (costs) узлов дерева плана, полученные от планировщика. Данные значения могут быть неточными и они никак не корректируются в процессе выполнения запроса.