RR: Czym różni się DELETE od TRUNCATE?

Pytanie zawarte w tytule wydaje się być banalne, ale spotkałem się już z osobami, które mimo dużego doświadczenia potrafiły udzielić nie do końca poprawnej odpowiedzi 😉

Nauka przez zabawę

Najprościej będzie wyjaśnić różnicę pomiędzy nimi za pomocą przykładów. Skorzystamy w nich z bazy StackOverflow2013 i tabeli dbo.Posts. Zaczniemy od wrzucenia pierwszych 100 000 wierszy do tabeli tymczasowej, na której będziemy przeprowadzać nasze eksperymenty.

DROP TABLE IF EXISTS #tempPosts;
SELECT TOP (100000)
    *
INTO #tempPosts
FROM
    [dbo].[Posts]
ORDER BY
    [Id];

Mamy już naszą tymczasową tabelę, więc najpierw wypróbujmy składnię z DELETE w celu usunięcia wszystkich danych z tabeli. Włączę również wyświetlanie statystyk czasu i odczytów oraz plan zapytania.

SET STATISTICS TIME, IO ON;
DELETE FROM #tempPosts;

Statystyki:

Table '#tempPosts'. Scan count 1, logical reads 18772, physical reads 0, page server reads 0,
read-ahead reads 0, page server read-ahead reads 0, lob logical reads 1033, lob physical reads 0,
lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.

(100000 rows affected)

SQL Server Execution Times:
CPU time = 359 ms, elapsed time = 389 ms.

Plan zapytania:

Nic nadzwyczajnego, szybki skan tabeli i usunięcie wszystkich wierszy. Dokonaliśmy przy tym 18772 odczytów (odczytami lob się tutaj nie interesujemy).

DELETE za nami, czas wypróbować TRUNCATE.

SET STATISTICS TIME, IO ON;
TRUNCATE TABLE #tempPosts;

Statystyki:

SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 3 ms.

Plan zapytania:

NULL

Co to się stanęło się? Statystyk żadnych, planu zapytania niet, czy na pewno wszystko się usunęło? Tak.

Różnica numer uno

DELETE jest operacją w pełni logowaną i operującą na poszczególnych wierszach w tabeli, więc aby usunąć wszystkie wiersze musi wykonać skan tabeli, a następnie każdy z otrzymanych wierszy fizycznie usunąć z pliku danych. TRUNCATE operuje na samych metadanych tabeli, oznaczając pierwszą stronę danych jako pustą, dzięki czemu jest minimalnie logowany i fizycznie nic nie usuwa, tylko informuje SQL Server, że “hej, to miejsce jest już wolne, nic tam nie ma”.

Wiąże się to jednak z pewnymi ograniczeniami TRUNCATE jakich nie posiada DELETE.

Wyobraźmy sobie, że chcemy usunąć tylko wpisy, których Id jest mniejsze od 1000. Przygotujmy więc zapytania z DELETE i TRUNCATE.

DELETE FROM #tempPosts WHERE [Id] < 1000;

TRUNCATE TABLE #tempPosts WHERE [Id] < 1000;

Zapytanie z funkcją DELETE wykonało się i rzeczywiście usunęło z tabeli wszystkie posty z Id mniejszym od 1000.

Natomiast zapytanie z TRUNCATE trochę się na nas obraziło.

Msg 156, Level 15, State 1, Line 13
Incorrect syntax near the keyword ‘WHERE’.

Różnica numer uno uno

Klauzula TRUNCATE nie pozwala na warunkowe usuwanie rekordów. Możemy usunąć tylko całą zawartość tabeli.

Pobawmy się trochę relacyjnością danych.

Ciekawostka – Wiązania FOREIGN KEY na tabelach tymczasowych nie są utrzymywane, dostajemy od SSMS taki ładny komunikat:

Skipping FOREIGN KEY constraint 'whisper' definition for temporary table. FOREIGN KEY constraints are not enforced on local or global temporary tables.

Musimy więc na nowo przygotować swoje dane, tym razem umieszczając je w “normalnych tabelach”.

DROP TABLE IF EXISTS dbo.tempFK;
DROP TABLE IF EXISTS dbo.tempPosts;

SELECT TOP(100000)
	*
INTO dbo.tempPosts
FROM
	[dbo].[Posts]
ORDER BY
	[Id];

ALTER TABLE dbo.tempPosts
ADD CONSTRAINT [evenindeath] PRIMARY KEY ([Id]);

CREATE TABLE dbo.tempFK ([Id] INT NOT NULL CONSTRAINT [whisper] FOREIGN KEY REFERENCES dbo.tempPosts([Id]));

Do naszej nowej tabeli nic nie wrzucamy, jest pusta. Spróbujmy następnie usunąć wszystkie wiersze z tabeli dbo.tempPosts przy pomocy DELETE.

DELETE FROM dbo.tempPosts;

Wszystko ładnie się wykonało, 100 000 wierszy usunięte, ale plan zapytania lekko się odmienił.

Doszedł nam skan naszej dodatkowej tabeli, powiązanej poprzez klucz obcy. SQL Server musiał sprawdzić każdy usuwany wiersz czy przypadkiem nie ma referencji do niego w naszej dodatkowej tabeli, gdyż wtedy usunięcie wiersza z kluczem głównym złamałoby zasadę spójności danych (klucz obcy zostałby osierocony i tak naprawdę prowadził donikąd). Możemy to łatwo zauważyć wrzucając do naszej dodatkowej tabeli wiersz z wartością 11 i następnie próbując usunąć dane. Dostaniemy wtedy taki błąd.

Msg 547, Level 16, State 0, Line 18
The DELETE statement conflicted with the REFERENCE constraint “whisper”. The conflict occurred in database “StackOverflow2013”, table “dbo.tempFK”, column ‘Id’.

No dobrze, ale wróćmy do pustej tabeli tempFK i klauzuli TRUNCATE.

TRUNCATE TABLE dbo.tempPosts;

Msg 4712, Level 16, State 1, Line 19
Cannot truncate table ‘dbo.tempPosts’ because it is being referenced by a FOREIGN KEY constraint.

Ojoj…

Różnica numer uno uno uno

TRUNCATE nie pozwala na usuwanie zawartości tabel, do których w schemacie bazy są odwołania poprzez klucz obcy. Nigdy. Jeżeli chcemy skorzystać z klauzuli TRUNCATE, wcześniej musimy usunąć wszystkie powiązania do tabeli.

I teraz truskawka na torcie. Jak poszczególne zapytania zachowają się w ramach transakcji, która została cofnięta?

BEGIN TRAN
    DELETE FROM dbo.tempPosts;
ROLLBACK
SELECT * FROM dbo.tempPosts;

Jak widać, wszystkie wiersze dalej są w tabeli, usunięcie ich zostało poprawnie wycofane. Czas na TRUNCATE.

BEGIN TRAN
    TRUNCATE TABLE dbo.tempPosts;
ROLLBACK
SELECT * FROM dbo.tempPosts;

I tutaj również wszystko pozostało na swoim miejscu.

NIE-różnica numer uno

Tak samo jak DELETE, TRUNCATE również podlega transakcyjności i można go normalnie wycofać!

Gdybym dostawał 5 zł od każdego, kto zapytany o różnice między DELETE a TRUNCATE mówił, że “TRUNCATE nie można ROLLBACKować” to już bym mógł spokojnie spędzić weekend w pubie i to takim z piwem za 20 zł. Nawet Microsoft na swojej stronie ma taką piękną ramkę, bo mit ciągle żyje wśród ludzi:

Pesky Microsoft

I jeszcze kilka różnic, o których warto pamiętać.

Różnica numer uno uno uno uno

Wykonanie DELETE na tabeli wymaga posiadania uprawnień na poziomie DELETE na tabeli. Wykonanie TRUNCATE na tabeli wymaga posiadania uprawnień na poziomie ALTER TABLE.

Różnica numer uno uno uno uno uno

TRUNCATE TABLE omija wywołanie wszystkich wyzwalaczy (triggerów) przypisanych do operacji DELETE na tabeli.

Podsumowanie

Różnic oczywiście jest więcej, jak niemożność uczestniczenia tabeli “trankejtowanej” w widoku indeksowanym czy też to, że taka tabela nie może być “temporal” (nie mylić z temporary!). Dla chętnych, tutaj informacje od źródła o ograniczeniach i różnicach:
https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-ver15#remarks

Oki, to pa!

Zobacz także:

  • Piotr Szymański

    Kategoria:

    Hejka! Zapraszam na skrót z minionych dwóch tygodni, który przyswoić możecie przy ciepłej herbatce w te mroczne, szare dni. W opublikowanym przez Google 14 listopada ostrzeżeniu wskazano kilka najważniejszych rodzajów oszustw internetowych. Uwagę zwrócono między na niebezpieczne techniki ataków typu cloaking, które nabierają nowego wymiaru dzięki wykorzystaniu sztucznej inteligencji. Cloaking polega na ukrywaniu przed użytkownikiem […]
  • Piotr Szymański

    Kategoria:

    Hejka po dłuższej przerwie! Zaczynamy świeżym tematem. Raptem kilkanaście godzin temu do użytkowników trafiła, zapowiedziana 25 lipca, funkcja SearchGPT od OpenAI, umożliwiająca, w przeciwieństwie do tradycyjnych modeli językowych, na integrację z internetem w czasie rzeczywistym. SearchGPT ma dostęp do aktualnych informacji z sieci, co pozwala na udzielanie odpowiedzi opartych na najnowszych danych. Ponadto SearchGPT dostarcza […]
  • Piotr Szymański

    Kategoria:

    Hejson! Dzisiejsza konsumpcja mediów ma to do siebie, że odbywa się na 5-6 calowym ekranie telefonu. Ma też to do siebie, że zanim zdjęcie dotrze do Ciebie, to przejdzie przez 6 konwersacji na jedynym słusznym messengerze, zatem zostanie 6-cio krotnie skompresowane. W międzyczasie, jak będziecie mieli pecha, to jakiś wujek zrobi screena, zamiast zapisać zdjęcie […]
  • Piotr Szymański

    Kategoria:

    Hej! Robimy bardzo dużo zdjęć, a co za tym idzie – wiele z nich jest niechlujnych, z zabałagnionym tłem. Możemy jednak chcieć wykorzystać je do pochwalenia się naszym ryjkiem na jakimś publicznym profilu, gdyż np. naturalne, miękkie światło korzystnie eksponuje naszą facjatę. Podejścia mogą być dwa – albo zdecydujemy się na blur bądź zupełne usunięcie […]
  • Piotr Szymański

    Kategoria:

    Strzałeczka. Nvidia przejęła OctoAI, startup specjalizujący się w optymalizacji modeli uczenia maszynowego. To już piąta akwizycja Nvidii w 2024 roku, co czyni aktualnie nam panujący rok rekordowym pod względem liczby przejęć. OctoAI, założone w 2019 roku przez Luisa Ceze, skupiło się na tworzeniu oprogramowania zwiększającego wydajność modeli uczenia maszynowego na różnych platformach sprzętowych. Oprogramowanie OctoAI […]