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 очистит и все зависимые таблицы. Используйте с осторожностью.