Оптимизация запросов PostgreSQL: Анализ EXPLAIN (ANALYZE, BUFFERS)
- Резкий рост утилизации CPU и дискового I/O при выполнении сложных аналитических запросов.
- Ошибки нехватки рабочей памяти
temporary file: path ... size ...в логах СУБД. - Неоптимальный выбор планировщиком полного сканирования таблицы (Seq Scan) вместо использования индексов.
1. Получение детализированного плана выполнения
Запустите анализ запроса с выводом реального времени исполнения, потребления буферов памяти и ввода-вывода:
EXPLAIN (ANALYZE, BUFFERS, SETTINGS, TIMING, COSTS)
SELECT o.id, o.created_at, c.name, SUM(i.price * i.quantity)
FROM orders o
JOIN customers c ON o.customer_id = c.id
JOIN order_items i ON i.order_id = o.id
WHERE o.created_at >= '2025-01-01'
GROUP BY o.id, o.created_at, c.name
ORDER BY o.created_at DESC
LIMIT 50;2. Ключевые узлы и метрики для анализа
- Buffers: shared hit vs read —
shared hitозначает чтение из RAM-кэша PostgreSQL,read— чтение с физического диска. Большое значениеreadтребует прогрева кэша или оптимизации выборки. - Rows Removed by Filter — неэффективный индекс: ядро читает блоки с диска и отбрасывает их на лету. Требуется композитный индекс.
- Sort Method: external merge Disk — СУБД не поместила операцию сортировки в
work_memи сбросила временные данные во временный файл на диск.
3. Оптимизация рабочей памяти сессии для тяжелых сортировок
-- Увеличение памяти для текущей транзакции
SET work_mem = '128MB';
-- Проверка и обновление устаревшей статистики планировщика
ANALYZE VERBOSE orders;
ANALYZE VERBOSE order_items; Частые вопросы (FAQ)
Выполняет ли EXPLAIN ANALYZE сам запрос физически?
Да. EXPLAIN ANALYZE выполняет запрос в СУБД на самом деле. Если выполнять его для команд INSERT, UPDATE или DELETE, данные в таблице будут модифицированы. Для безопасного теста оборачивайте запрос в блок BEGIN; ... ROLLBACK;.
Что означает разница между rows=1 (estimate) и actual rows=500000?
Это указывает на устаревшую статистику в системном каталоге pg_statistic или отсутствие расширенной статистики (CREATE STATISTICS) по зависимым колонкам. Планировщик ошибается при выборе алгоритма соединения.
Почему планировщик выбирает Seq Scan вместо Index Scan на большой таблице?
Если запрос запрашивает существенный процент строк таблицы (обычно > 10-20%), последовательное чтение блоков (Seq Scan) выполняется быстрее случайного позиционирования по индексу из-за предвыборки страниц ядром ОС.
Что показывает параметр shared dirtied и shared written?
shared dirtied отображает количество страниц shared buffers, которые были модифицированы данным запросом; shared written — сколько страниц сессия была вынуждена сбросить на диск самостоятельно.