lesson ── postgres-labs ── ~22 мин ── 4 шагов
pg_stat_statements агрегирует выполнение по нормализованному тексту запроса: разные значения параметров схлопываются в один шаблон. Ты создашь два вида нагрузки - частую дешёвую и редкую дорогую - и увидишь, почему виновника ищут по суммарному времени, а не по среднему. Сначала предсказывай, потом проверяй.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
Расширение pg_stat_statements уже загружено в этот сервер (через shared_preload_libraries). Сбрось счётчики, чтобы мерить с чистого листа:
SELECT pg_stat_statements_reset();
Предскажи: вернёт ли запрос ниже ровно одну строку про установленное расширение?
✓ Расширение на месте, счётчики сброшены.
Выполни короткий запрос по первичному ключу много раз (повтори строку десяток-другой раз, меняя номер):
SELECT * FROM tickets WHERE ticket_no = '0000000000001';
SELECT * FROM tickets WHERE ticket_no = '0000000000002';
-- ... повтори ещё много раз с разными номерами ...
Предскажи: схлопнутся ли все эти вызовы в одну строку
pg_stat_statements (с нормализованным ticket_no = $1)?
Чтобы быстро нагенерировать вызовы, можно повторить строку 10-20 раз с разными номерами.
✓ Все вызовы схлопнулись в одну строку с большим calls.
Выполни один раз тяжёлое соединение по всем билетам:
SELECT count(*) FROM tickets t JOIN bookings b ON b.book_ref = t.book_ref;
Предскажи: его calls будет около 1, но total_exec_time за один вызов может оказаться сравнимым с сотнями дешёвых.
✓ Дорогой запрос записан отдельной строкой.
Посмотри топ по суммарному времени:
SELECT calls, round(total_exec_time) AS total_ms,
round(mean_exec_time, 2) AS mean_ms, left(query, 50) AS q
FROM pg_stat_statements
ORDER BY total_exec_time DESC LIMIT 5;
Теперь то же, но ORDER BY mean_exec_time DESC. Предскажи: наверху
окажутся разные запросы? В этом и смысл выбора метрики - total
показывает реального виновника нагрузки.
✓ Оба класса запросов в отчёте. Виновника нагрузки выбирают по total_exec_time.
pg_stat_statements - главный отчёт о нагрузке: одна строка на нормализованный запрос с суммой по всем вызовам. Виновника ищут по total_exec_time, а не по mean: частота важнее цены одного вызова.
команды
SELECT pg_stat_statements_reset();сбросить счётчики для чистого замераSELECT query, calls, total_exec_time FROM pg_stat_statements ORDER BY total_exec_time DESC;топ по суммарному времениконцепции