Дерево плана, строки, повторы, буферы, временные файлы и честное сравнение
EXPLAIN показывает план, который выбрал PostgreSQL. Обычный EXPLAIN только
строит оценку и не выполняет запрос. EXPLAIN ANALYZE действительно выполняет
его и добавляет фактические строки и время.
Поэтому EXPLAIN ANALYZE DELETE ... удалит данные, а UPDATE изменит их. Для
команд записи используйте отдельную копию базы. Транзакция с откатом подходит
только тогда, когда допустимы все временные блокировки, триггеры и внешние
побочные действия:
BEGIN;
EXPLAIN (ANALYZE, BUFFERS, WAL, SETTINGS, FORMAT JSON)
UPDATE marketplace.inventory
SET reserved = reserved + 1
WHERE product_id = 1 AND reserved < available;
ROLLBACK;ROLLBACK отменит изменение таблицы, но не отменит отправленный триггером
сетевой запрос. Формат JSON удобен для автоматического сравнения планов.
Нижние узлы получают строки из таблиц и индексов. Верхние фильтруют, сортируют, соединяют и агрегируют результаты. Отступ показывает родителя и ребёнка.
Основные поля узла:
actual time=a..b — время до первой и до последней строки;rows=n — число строк за одно выполнение;loops=k — сколько раз узел повторялся;Rows Removed by Filter — сколько строк прочитано, но отброшено условием;Buffers: shared hit — страницы найдены в общем кеше;Buffers: shared read — страницы пришлось прочитать с хранилища;dirtied и written — страницы изменены и записаны;temp read/write — промежуточные данные вышли из памяти во временный файл;WAL records/bytes — объём журнала, созданный изменением.Время дочернего узла уже входит во время родителя, поэтому складывать времена всех строк плана нельзя. Ищите неожиданно большой объём строк, много повторов, запись временного файла и первую сильную ошибку оценки.
Изменение «ускорило запрос со 120 до 80 мс» ещё ничего не доказывает: второй запуск мог прочитать страницы из кеша. Работайте по шагам.
Нет универсального правила «последовательное чтение плохо после 10 000 строк» или «индекс нужен, если выбирается меньше 30%». Важны ширина строки, кеш, физический порядок, скорость диска и одновременная нагрузка.
Оценка строк сильно ошиблась. Обновите статистику, проверьте перекос и связь столбцов, при необходимости создайте расширенную статистику.
Index Only Scan много раз читает таблицу. Посмотрите Heap Fetches,
карту видимости, частоту изменений и работу autovacuum.
Вложенный цикл повторяет внутренний узел тысячи раз. Возможно, неверно оценено число строк или отсутствует подходящий путь доступа.
Сортировка или хеш ушли на диск. Сначала сократите набор раньше, проверьте
индекс и форму запроса. Только потом локально экспериментируйте с work_mem.
SELECT * читает большие значения. Выберите только нужные столбцы, чтобы
не читать и не распаковывать TOAST без необходимости.
В лаборатории 21 вы сохраните планы JSON до и после изменения и примете решение по чтениям и оценкам, а не по одному времени.
Подробнее: использование EXPLAIN.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.
Далее: Индексы: ускорение чтения и его цена