Гост автор:Дерик Хамър (@SQLHammer)
Разликите между TRUNCATE TABLE и DELETE често се разбират погрешно. Опитвам се да опровергая мита, че TRUNCATE TABLE не може да се върне назад:
Четене на ръководството
Статията на Books Online за TRUNCATE TABLE е доста описателна:
„Премахва всички редове от таблица или определени дялове на таблица, без да регистрира отделните изтривания на редове. TRUNCATE TABLE е подобен на оператора DELETE без клауза WHERE; обаче TRUNCATE TABLE е по-бърз и използва по-малко ресурси на системата и регистрационните файлове на транзакциите."Фактът, че TRUNCATE TABLE използва по-малко Ресурсите на дневника на транзакциите предполагат, че той записва до известна степен в регистъра на транзакциите. Нека да разберем колко и да проучим способността му да бъде връщан назад.
Докажи го
В по-ранна публикация Пол Рандъл разглежда това в детайли, но реших, че би било полезно да предоставя много прости повторения, за да опровергае и двата елемента на този мит.
Може ли да се върне TRUNCATE TABLE?
Доказателството, че TRUNCATE TABLE може да се върне назад, е достатъчно лесно. Просто ще сложа TRUNCATE TABLE в транзакция и ще я върна обратно.
USE demo; BEGIN TRANSACTION; SELECT COUNT(*) [StartingTableRowCount] FROM [dbo].[Test]; TRUNCATE TABLE [dbo].[Test]; SELECT COUNT(*) [TableRowCountAfterTruncate] FROM [dbo].[Test]; ROLLBACK TRANSACTION; SELECT COUNT(*) [TableRowCountAfterRollback] FROM [dbo].[Test];
В таблицата има 100 000 реда и тя се връща до 100 000 реда след връщане назад:
TRUNCATE TABLE записва ли в дневника?
Чрез изпълнение на CHECKPOINT получаваме чиста отправна точка. След това можем да проверим регистрационните записи преди и след TRUNCATE TABLE.
USE demo; CHECKPOINT; SELECT COUNT(*) [StartingLogRowCount] FROM sys.fn_dblog (NULL, NULL); TRUNCATE TABLE [dbo].[Test]; SELECT COUNT(*) [LogRowCountAfterTruncate] FROM sys.fn_dblog (NULL, NULL);
Нашата команда TRUNCATE TABLE генерира 237 дневника (поне първоначално). Това е, което ни позволява да извършим връщане назад и как SQL Server регистрира промяната за начало.
Какво ще кажете за DELETE?
Ако и DELETE, и TRUNCATE TABLE записват в дневника и могат да бъдат върнати назад, какво ги прави различни?
Както бе споменато в препратката за BOL по-горе, TRUNCATE TABLE отнема по-малко ресурси на системата и регистрационните файлове на транзакциите. Вече забелязахме, че за командата TRUNCATE TABLE са записани 237 дневника. Сега нека разгледаме ИЗТРИВАНЕ.
USE demo; CHECKPOINT; SELECT COUNT(*) [StartingLogRowCount] FROM sys.fn_dblog (NULL, NULL); DELETE FROM [dbo].[Test]; SELECT COUNT(*) [LogRowCountAfterDelete] FROM sys.fn_dblog (NULL, NULL);
С над 440 000 регистрационни записи, написани за DELETE, командата TRUNCATE очевидно е много по-ефективна.
Заключение
TRUNCATE TABLE е регистрирана команда и може да бъде върната назад, с огромно предимство в производителността пред еквивалентно DELETE. DELETE става важен, когато искате да изтриете по-малко редове, отколкото съществуват в таблицата (тъй като TRUNCATE TABLE не приема клауза WHERE). За някои идеи как да направите DELETE по-ефективни, вижте публикацията на Aaron Bertrand „Разбийте големи операции за изтриване на парчета.