Материалы / Технические статьи / Как анализировать DML через EXPLAIN
Статья

Как анализировать DML через EXPLAIN

Как исследовать планы UPDATE, DELETE и INSERT и почему EXPLAIN ANALYZE для изменяющих запросов требует особой осторожности.

Кофе давно остыл. Монитор гипнотизировал Лену мигающим курсором.

— Мучаешь базу? — раздался за спиной голос Макса. Он стоял, прислонившись к дверному косяку с пустой кружкой в руке.

— Это не я, это UPDATE, — вздохнула Лена. — Просто меняет статусы у старых задач. Что тут может быть не так?

— Ты думаешь, это простая операция. А я говорю: твой UPDATE — это приговор производительности.

Лена развернулась на стуле.

— Приговор? Макс, это же не сложный SELECT с кучей JOINов. Это просто UPDATE…

— Ну и что? Прежде чем обновить, база должна найти. А как она ищет? Через планировщик — фактически тем же способом, как если бы выполняла SELECT.

Он подошёл ближе и кивнул на монитор:

— Попробуй EXPLAIN, без ANALYZE. Тогда база просто покажет план, не выполняя сам запрос.

— Хочешь сказать, что EXPLAIN работает и с UPDATE?

— Конечно. Все DML операторы можно анализировать через EXPLAIN.

— И EXPLAIN ANALYZE можно? он же фактически выполняет запрос.

— Можно и EXPLAIN ANALYZE, — кивнул Макс. — Он действительно выполнит UPDATE. На изолированном стенде его иногда оборачивают в транзакцию и завершают ROLLBACK:

BEGIN;
EXPLAIN (ANALYZE, BUFFERS)
UPDATE tasks
SET status = 'archived'
WHERE created_at < date '2024-01-01';
ROLLBACK;

— Но ROLLBACK не делает эксперимент бесплатным и полностью обратимым. Запрос всё равно берёт блокировки, пишет WAL, создаёт нагрузку и может надолго удержать старые версии строк. Значения sequence не откатываются, а пользовательские функции и триггеры могут иметь внешние побочные эффекты. На продакшене такой запуск без отдельной оценки недопустим.

Лена нахмурилась.

— Но это же разовая ручная операция. Не создавать же индекс ради неё?

— Я знаю, что я зануда, — улыбнулся Макс. — Конечно ты права, для единичных действий индекс — только балласт. Просто обратил твое внимание, что анализировать и оптимизировать можно и нужно не только SELECTы.

Он сделал глоток остывшего кофе и добавил:

— Вот взять INSERT. Думаешь, это быстро. А потом выясняется, что на каждую вставку срабатывают триггеры: журналирование, проверки, дополнительная обработка. В EXPLAIN ANALYZE время триггеров видно отдельно, но саму операцию безопаснее исследовать на репрезентативном стенде.

— Аж захотелось посмотреть, как работает INSERT с ON CONFLICT. — задумалась Лена.

— Да, UPSERT тот ещё артист. Сначала проверит конфликт — фактически ищет строку через индекс, — потом решит, вставлять или обновлять. И план все покажет.

— Значит, любая DML-операция…

— …это не только изменение строк, — продолжил Макс. — Нужно понять, как PostgreSQL находит целевые строки, проверяет ограничения и индексы и какие триггеры запускает. Только тогда можно осмысленно ускорять операцию.

Он подмигнул и пошёл к кофемашине.

А Лена, глядя на экран, решила ничего не менять.

Медленный запрос — не приговор, а симптом.

И вообще, оптимизировать стоит не только запросы, но и своё время, и силы.