Почему «удаление из таблицы» занимает много времени, когда «усечение таблицы» занимает 0 времени?

(Я пробовал это в MySql)

Я считаю, что они семантически эквивалентны. Почему бы не выявить этот тривиальный случай и не ускорить его?


person ripper234    schedule 24.12.2008    source источник


Ответы (6)


таблицу truncate нельзя откатить, это все равно что отбрасывать и воссоздавать таблицу.

person Otávio Décio    schedule 24.12.2008
comment
truncate не нужно добавлять записи журнала - person Traingamer; 24.12.2008
comment
В MySQL таблица TRUNCATE не удаляет таблицу, она УДАЛЯЕТ все записи и устанавливает значение auto_increment равным 1 - person Petr Peller; 27.07.2011

... просто чтобы добавить деталей.

Вызов оператора DELETE указывает ядру базы данных создать журнал транзакций для всех удаленных записей. В случае, если удаление было выполнено по ошибке, вы можете восстановить свои записи.

Вызов оператора TRUNCATE - это сплошное «все или ничего», которое удаляет все записи без журнала транзакций для восстановления. Это определенно быстрее, но это следует делать только тогда, когда вы уверены, что вам не нужны никакие записи, которые вы собираетесь удалить.

person Dillie-O    schedule 24.12.2008
comment
Разве это не означает, что если другие процессы / потоки действуют с этой таблицей, они могут получить несогласованное представление? Или что в противном случае это было бы заблокировано до тех пор, пока не будут выполнены другие запросы к таблице? - person Paul Tomblin; 24.12.2008
comment
@Paul Tomblin: будут ли другие процессы заблокированы или имеют несогласованное чтение, будет зависеть от используемого механизма таблицы и любой настроенной семантики блокировки. - person Toby Hede; 25.12.2008

Удалить из таблицы удаляет каждую строку по одной и добавляет запись в журнал транзакций, чтобы можно было выполнить откат операции. Время, необходимое для удаления, также пропорционально количеству индексов в таблице и наличию каких-либо ограничений внешнего ключа (для innodb).

Усечение эффективно удаляет таблицу и воссоздает ее и не может быть выполнено в рамках транзакции. Поэтому требуется меньше операций и выполняется быстро. Truncate также не использует никаких триггеров удаления.

Точные сведения о том, почему это быстрее в MySql, можно найти в документации MySql: http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html

person Pervez Choudhury    schedule 24.12.2008
comment
+1 за упоминание индексов ... хотя и правда, что существуют умные способы уменьшения индексов во время удаления, использование наивного метода по одному может быть очень дорогостоящим из-за того, как вы сокращаете дерево B +. - person Ian Varley; 25.12.2008

Ваш вопрос касался MySQL, и я почти ничего не знаю о MySQL как продукте, но я подумал, что добавлю, что в SQL Server оператор TRUNCATE можно откатить. Попробуйте сами

create table test1 (col1 int)
go
insert test1 values(3)
begin tran
truncate table test1
select * from test1
rollback tran
select * from test1

В SQL Server TRUNCATE регистрируется, просто он не регистрируется таким подробным способом, как DELETE. Я считаю, что это называется операцией с минимальным протоколированием. Фактически страницы данных все еще содержат данные, но их экстенты отмечены для удаления. Пока страницы данных все еще существуют, вы можете откатить усечение. Надеюсь, это будет полезно. Мне было бы интересно узнать результаты, если кто-нибудь попробует это на MySQL.

person Eric Sabine    schedule 25.12.2008
comment
Правильно, и есть хорошая статья на weblogs.sqlteam.com/mladenp/archive/2007/10/03/, который объясняет различия - в SQL Server. - person Cade Roux; 26.12.2008

Для MySql 5, использующего InnoDb в качестве механизма хранения, TRUNCATE действует так же, как DELETE без предложения WHERE: т.е. для больших таблиц требуется время, потому что он удаляет строки одну за другой. Это изменилось в версии 6.x.

видеть

http://dev.mysql.com/doc/refman/5.1/en/truncate-table.html

для информации 5.1 (строка за строкой с InnoDB) и

http://blogs.mysql.com/peterg/category/personal-opinion/ < / а>

для изменений в 6.x


Примечание редактора

Этот ответ явно противоречит документации MySQL:

Для таблицы InnoDB до версии 5.0.3 InnoDB обрабатывает TRUNCATE TABLE, удаляя строки одну за другой. Начиная с MySQL 5.0.3, удаление строки за строкой используется, только если есть какие-либо ограничения FOREIGN KEY, которые ссылаются на таблицу. Если ограничений FOREIGN KEY нет, InnoDB выполняет быстрое усечение, удаляя исходную таблицу и создавая пустую с тем же определением, что намного быстрее, чем удаление строк по одной.

person davek    schedule 25.09.2009
comment
Это не правильно. В документации указано, что MySQL 5.0.3 и более поздние версии удаляют и воссоздают таблицу БЕЗ ограничений внешнего ключа, и в этом случае он удаляет строку за строкой. - person DougW; 27.11.2013

Усечение находится на уровне таблицы, а удаление - на уровне строки. Если вы переведете это в sql с другим синтаксисом, усечение будет таким:

DELETE * FROM table

таким образом удаляя все строки сразу, а инструкция DELETE (в PHPMyAdmin) выглядит так:

DELETE * FROM table WHERE id = 1
DELETE * FROM table WHERE id = 2

Пока стол не опустеет. Каждый запрос занимает количество (милли) секунд, что в сумме занимает больше времени, чем усечение.

person jvermolen    schedule 14.08.2013