DELETE vs TRUNCATE — в чём разница и когда что использовать

Коротко

DELETE удаляет строки по одной, поддерживает WHERE, триггеры и RETURNING. TRUNCATE мгновенно очищает всю таблицу, но не поддерживает условий.

Как работает DELETE

DELETE удаляет строки, соответствующие условию WHERE. Каждая удалённая строка логируется в WAL (журнале транзакций), что позволяет откатить операцию.

-- Удалить неактивных пользователей
DELETE FROM users WHERE last_login < '2024-01-01';

-- Удалить все строки (медленно для больших таблиц)
DELETE FROM users;

Как работает TRUNCATE

TRUNCATE не удаляет строки по одной — он освобождает все страницы данных разом. Это в разы быстрее, но нельзя указать условие.

-- Очистить таблицу целиком
TRUNCATE TABLE users;

-- Очистить несколько таблиц + сбросить автоинкремент
TRUNCATE TABLE orders, order_items RESTART IDENTITY;

Ключевые отличия

DELETE TRUNCATE
WHERE Поддерживает Нет
Скорость Медленнее (построчно) Очень быстро
Триггеры Строчные (row-level) срабатывают Строчные не срабатывают (statement-level TRUNCATE-триггеры — да, в PostgreSQL)
RETURNING Поддерживает Нет
Откат (ROLLBACK) Да Да (в PostgreSQL)
Автоинкремент Не сбрасывает Можно сбросить (RESTART IDENTITY)
Внешние ключи Проверяются CASCADE или ошибка

Производительность

На таблице с миллионом строк DELETE FROM table (без WHERE) может работать минуты. TRUNCATE — доли секунды.

Причина: DELETE записывает информацию о каждой удалённой строке в журнал транзакций. TRUNCATE просто помечает все страницы данных как свободные.

На практике: аналитики редко выполняют DELETE или TRUNCATE в продакшене. Но понимать разницу важно для задач по проектированию ETL-пайплайнов и обновлению витрин данных.

Важный нюанс: TRUNCATE в транзакции

В PostgreSQL TRUNCATE транзакционный — его можно откатить:

BEGIN;
TRUNCATE TABLE staging_data;
-- Если что-то пошло не так:
ROLLBACK;  -- данные вернутся

В MySQL TRUNCATE неявно коммитит транзакцию — откатить нельзя.

Вопросы с собеседований

  • «Чем DELETE без WHERE отличается от TRUNCATE?» — Результат одинаковый, но TRUNCATE быстрее, не вызывает триггеры и может сбросить автоинкремент.
  • «Можно ли откатить TRUNCATE?» — В PostgreSQL да (он транзакционный). В MySQL нет.
  • «Когда использовать DELETE, а когда TRUNCATE?» — DELETE для выборочного удаления. TRUNCATE для полной очистки таблицы (стейджинг, временные данные).

FAQ

Что быстрее для удаления части строк — DELETE или TRUNCATE + INSERT?

Если удаляете большую часть таблицы (> 50%), может быть быстрее: CREATE TABLE new AS SELECT ... WHERE condition, DROP TABLE old, ALTER TABLE new RENAME TO old. Но это сложнее и опаснее.

TRUNCATE удаляет структуру таблицы?

Нет. Таблица остаётся со всеми колонками, индексами и ограничениями. Удаляются только данные. Для удаления самой таблицы используйте DROP TABLE.

Что делает TRUNCATE CASCADE?

Если на таблицу ссылаются внешние ключи, TRUNCATE CASCADE очистит и все зависимые таблицы. Используйте с осторожностью.