linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/lessons/pg-lab-40-1-find-slow-sql

lesson ── postgres-labs ── ~22 мин ── 4 шагов

Найди медленный SQL через pg_stat_statements

pg_stat_statements агрегирует выполнение по нормализованному тексту запроса: разные значения параметров схлопываются в один шаблон. Ты создашь два вида нагрузки - частую дешёвую и редкую дорогую - и увидишь, почему виновника ищут по суммарному времени, а не по среднему. Сначала предсказывай, потом проверяй.

▶ интерактивный sandbox

Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.

запустить sandbox →

stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя

Шаги

  1. 01

    Сбрось статистику и проверь расширение

    Расширение pg_stat_statements уже загружено в этот сервер (через shared_preload_libraries). Сбрось счётчики, чтобы мерить с чистого листа:

    sql
    SELECT pg_stat_statements_reset();

    Предскажи: вернёт ли запрос ниже ровно одну строку про установленное расширение?

    ✓ Расширение на месте, счётчики сброшены.

  2. 02

    Создай частую дешёвую нагрузку

    Выполни короткий запрос по первичному ключу много раз (повтори строку десяток-другой раз, меняя номер):

    sql
    SELECT * FROM tickets WHERE ticket_no = '0000000000001';
    SELECT * FROM tickets WHERE ticket_no = '0000000000002';
    -- ... повтори ещё много раз с разными номерами ...

    Предскажи: схлопнутся ли все эти вызовы в одну строку pg_stat_statements (с нормализованным ticket_no = $1)?

    подсказка

    Чтобы быстро нагенерировать вызовы, можно повторить строку 10-20 раз с разными номерами.

    ✓ Все вызовы схлопнулись в одну строку с большим calls.

  3. 03

    Добавь редкий дорогой запрос

    Выполни один раз тяжёлое соединение по всем билетам:

    sql
    SELECT count(*) FROM tickets t JOIN bookings b ON b.book_ref = t.book_ref;

    Предскажи: его calls будет около 1, но total_exec_time за один вызов может оказаться сравнимым с сотнями дешёвых.

    ✓ Дорогой запрос записан отдельной строкой.

  4. 04

    Сравни сортировку по total и по mean

    Посмотри топ по суммарному времени:

    sql
    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;топ по суммарному времени

концепции

  • · pg_stat_statements нормализует запросы: WHERE id=1 и id=2 - одна строка
  • · виновника нагрузки ищут по total_exec_time, не по mean_exec_time
  • · это накопленный счётчик: смысл в дельте между замерами

← предыдущая

Подними логическую подписку и проведи строку от источника к приёмнику

следующая →

work_mem и проливы сортировки на диск

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки