DELETE FROM orders видаляє рядки по одному: позначає кожен як видалений (MVCC), запускає тригери ON DELETE, перевіряє зовнішні ключі, може мати WHERE. Місце звільняється пізніше, вакуумом.
TRUNCATE orders звільняє таблицю цілком - фактично підміняє файли таблиці порожніми. Миттєво навіть на мільярді рядків, і місце повертається одразу.
Відмінності:
DELETE |
TRUNCATE |
|
|---|---|---|
Умова WHERE |
так | ні, лише вся таблиця |
| Швидкість на великій таблиці | повільно, пропорційно кількості рядків | миттєво |
| Тригери на рядки | спрацьовують | ні (є окремі ON TRUNCATE) |
| Блокування | рядків | ексклюзивне на таблицю (ACCESS EXCLUSIVE) |
Лічильник identity/serial |
не скидає | скидає з RESTART IDENTITY |
| Зовнішні ключі | перевіряються по рядках | помилка, якщо на таблицю посилаються, без CASCADE |
Чи можна відкотити: у PostgreSQL так - TRUNCATE транзакційний:
BEGIN;
TRUNCATE orders;
ROLLBACK; -- дані на місці
У MySQL TRUNCATE - DDL-команда з неявним комітом, і відкотити її не можна.
Застереження:
TRUNCATEбере найсильніше блокування: поки транзакція з ним не завершилася, таблицю не може читати ніхто.TRUNCATE ... CASCADEочистить і всі таблиці, що посилаються на цю, - легко знищити більше, ніж планували.- У тестах
TRUNCATEміж тестами - швидкий спосіб очищення (так працюєDatabaseTruncationу Laravel), але транзакція з відкатом (RefreshDatabase) ще швидша.