Профилирование долгих запросов
Данная функциональность позволяет отслеживать состояние выполнения запроса, не дожидаясь его окончания. Стоит учитывать, что включение профилирования привносит некоторое количество затрат для всех запросов серверного процесса.
Подготовка
Для включения профилирования необходимо установить параметр 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 и отображает дерево плана запроса. Второй аргумент принимает строку со способом форматирования:
- 'full' — отображает полные значения счетчиков;
- 'scaled' — отображает значения счетчиков приведенные к одному порядку (отображается в поле units);
- 'scientific' — отображает значения счетчиков;
- 'percent' — отображает значения счетчиков в процентах;
- 'mixed_percent' — отображает значения счетчиков в процентах и абсолютное ожидаемое значение;
Функция возвращает дерево плана, равнозначное тому, что возвращает EXPLAIN
,
а также статус выполнения для каждого узла. Стоит иметь в виду, что узлы могут
иметь прогресс в 100%, но тем не менее вызываться повторно, увеличивая счетчик
циклов. Пример анализа запроса:
# 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 предсказывается интерполяцией всего по двум точкам во времени, что означает, что это значение может достаточно сильно колебаться с течением времени.
- Для анализа работы запроса используются оценки затрат узлов дерева плана, полученные от планировщика. Данные значения могут быть неточными, и они никак не корректируются в процессе выполнения запроса.