TRUNCATE — Penghapusan Massal yang Cepat dan High Water Mark

Panduan visual untuk perbedaan antara DELETE dan TRUNCATE: cara kerja High Water Mark (HWM), apakah kamu bisa rollback setelah menjalankannya, alasan sesungguhnya di balik perbedaan kecepatan, dan cara memilih di antara mereka di Oracle / PostgreSQL / MySQL.

Kode di artikel ini ditujukan untuk RDBMS produksi

Sintaks TRUNCATE TABLE di artikel ini adalah bentuk yang dipakai oleh RDBMS produksi seperti MySQL / PostgreSQL / Oracle / SQL Server. Konsol browser untuk kursus ini (yang memakai SQLite) tidak menerima kata kunci TRUNCATE secara langsung. Di SQLite, DELETE FROM tabel; punya efek yang sama, dan truncate optimization internal membuatnya berjalan secepat TRUNCATE.

TRUNCATE — menghapus setiap baris, dengan cepat

Ada dua cara untuk menghapus setiap baris di tabel sekaligus. Yang satu adalah DELETE FROM tabel; (tanpa WHERE), yang sudah dibahas di artikel sebelumnya. Yang lain adalah `TRUNCATE TABLE tabel;`, topik artikel ini. Keduanya meninggalkan tabel kosong, tapi bagaimana caranya dan seberapa cepat berjalan benar-benar berbeda.

DELETE adalah perintah DML (Data Manipulation Language) yang menghapus baris satu per satu, meninggalkan entri log untuk setiap penghapusan. TRUNCATE, di sisi lain, condong ke DDL (Data Definition Language) — ia mereset seluruh tabel tanpa pencatatan per baris, hampir seperti definisi tabelnya sendiri dibuat ulang dari awal.

Bagaimana DELETE dan TRUNCATE berbeda
DELETE FROM tabel;TRUNCATE TABLE tabel;Hapus baris satu per satu(bisa dipersempit dengan WHERE)Reset tabel sekaligus(WHERE tidak diperbolehkan)Diperlakukan sebagai DMLBisa di-rollbackDiperlakukan sebagai DDL(tergantung DB)Bisa commit saat eksekusiLog delete per barisMemicu triggerLogging minimalUmumnya melewati triggerLambat di tabel besarInstan bahkan di tabel besar
DELETE adalah perintah DML yang menghapus baris satu per satu dan menyimpan log; TRUNCATE condong ke DDL dan mereset seluruh tabel sekaligus. Keduanya berbeda dalam dukungan WHERE, rollback setelah eksekusi, dan kecepatan.
-- 1) DELETE semuanya (log delete per baris, bisa di-rollback)
DELETE FROM customer;

-- 2) TRUNCATE semuanya (reset sekali jalan, tanpa log per baris, biasanya commit langsung)
TRUNCATE TABLE customer;

-- Catatan: konsol kursus ini (SQLite) tidak menerima TRUNCATE.
--   DELETE FROM customer; mendapat truncate optimization yang sama secara internal dan berjalan cepat.

Perbedaan antara MySQL / PostgreSQL / Oracle

Sintaks TRUNCATE TABLE tabel; itu sendiri sama di MySQL / PostgreSQL / Oracle / SQL Server, tapi perilaku detailnya berbeda per DB.

- MySQL: Diperlakukan sebagai DDL, tidak bisa di-rollback, AUTO_INCREMENT di-reset

- PostgreSQL: Bisa di-rollback, RESTART IDENTITY mereset sequence juga

- Oracle: Diperlakukan sebagai DDL, tidak bisa di-rollback, REUSE STORAGE / DROP STORAGE membuatmu bisa mengontrol cara storage dikembalikan

- SQL Server: Bisa di-rollback

High Water Mark — apa yang ada di balik perbedaan kecepatan

Kunci untuk memahami perbedaan kecepatan antara DELETE dan TRUNCATE adalah konsep High Water Mark (HWM). HWM adalah penanda yang menunjuk ke blok storage tertinggi yang pernah dipakai tabel. Istilah ini berasal dari Oracle, tapi PostgreSQL / SQL Server / MySQL (InnoDB) semuanya punya optimisasi setara yang bekerja secara internal.

Saat DB melakukan full scan (sapu baris per baris seperti SELECT * FROM tabel), ia membaca setiap blok dari awal tabel sampai HWM secara berurutan. Semakin tinggi HWM, semakin banyak blok yang harus dibaca — dan karena ia tidak melewati blok kosong, scan bisa lambat bahkan di tabel kosong kalau HWM-nya tinggi.

Cara kerja High Water Mark (HWM)
Target scan = blok pada atau di bawah HWM── HWM (block 5) ──Posisi tertinggi yangpernah dipakai tabelblock 5: ●dataFull scan membacasemua di bawah iniblock 4: ●datablock 3: ●datablock 2: ●datablock 1: ●dataAwal tabel(block 0)
Di dalam tabel ada urutan blok berukuran tetap. HWM menandai 'blok tertinggi yang pernah dipakai.' Full scan membaca setiap blok pada atau di bawah HWM.

Perilaku krusial di sini adalah DELETE tidak menurunkan HWM. Saat kamu menjalankan DELETE FROM tabel; untuk menghapus setiap baris, isi tabel jadi kosong, tapi blok-bloknya sendiri tetap di segment. HWM tetap di block 5. Jalankan SELECT COUNT(*) FROM tabel; berikutnya, dan walau jumlah baris adalah 0, DB membaca setiap blok pada atau di bawah HWM sampai akhir — memakan waktu yang kira-kira sama seperti sebelum delete.

TRUNCATE TABLE tabel; adalah perintah yang mereset HWM kembali ke awal tabel, secara instan menyusutkan target full-scan menjadi 0 blok. Itulah alasan sesungguhnya kenapa TRUNCATE digambarkan sebagai "instan bahkan di tabel besar."

HWM setelah DELETE vs setelah TRUNCATE
StatusAwal (5 baris)DELETE FROMtabel;TRUNCATE TABLEtabel;Jumlah baris5 baris0 baris0 barisBlok5 dipakai5 (kosong)ResetHWMblock 5tetapblock 5reset keblock 0Full scan5 blok5 blok(termasuk kosong)0 blok(instan)
Setelah keduanya, jumlah baris adalah 0. Tapi posisi HWM berbeda, yang membuat perbedaan besar di kecepatan full-scan berikutnya.

DELETE tidak menyusutkan datanya?

Saya pernah mengalami situasi di produksi di mana saya menjalankan DELETE untuk mengurangi ukuran data, tapi pemakaian storage hampir tidak turun.

Penyebabnya persis ini: HWM tidak turun. DELETE hanya menghapus baris secara logis, sementara blok (page) yang sudah direservasi tabel tetap di tempat. File di disk masih menyimpan area itu, jadi dari perspektif OS ukuran datanya tidak berubah.

Saat kamu benar-benar ingin menyusutkan storage, jalankan perintah reorganisasi per-DB (VACUUM FULL di PostgreSQL, OPTIMIZE TABLE di MySQL InnoDB, ALTER TABLE ... SHRINK SPACE di Oracle), atau pakai TRUNCATE untuk full wipe.

Memilih antara DELETE dan TRUNCATE

Dalam praktik, pilihannya bukan sekadar "TRUNCATE untuk semuanya, DELETE saat butuh kondisi." Faktor sebenarnya adalah apakah kamu butuh rollback, apakah trigger harus ter-fire, dan seberapa penting kecepatan pemrosesan. Tabel perbandingan di bawah adalah checklist standar.

ItemDELETETRUNCATE
GranularitasPer barisSeluruh tabel
Klausa WHEREDiperbolehkanTidak diperbolehkan (selalu semua baris)
Kecepatan (tabel besar)Lambat (proses per baris)Cepat (instan)
Rollback setelah eksekusiMungkinTergantung DB (Oracle / MySQL: tidak)
Trigger ter-fireTer-fireUmumnya tidak ter-fire
AUTO_INCREMENTDipertahankanReset (tergantung DB)
High Water MarkTidak bergerakReset
Log deleteEntri per baris (besar)Minimal
KlasifikasiDMLDDL (tergantung DB)

Jebakan TRUNCATE

TRUNCATE itu cepat dan praktis, tapi cenderung jadi operasi yang tidak bisa kamu tarik kembali. Hati-hati dengan:

- Beberapa DB commit saat eksekusi (Oracle / MySQL). Di produksi, jalankan SELECT COUNT(*) lebih dulu untuk memastikan jumlah baris sebelum menjalankannya

- `AUTO_INCREMENT` di-reset (tergantung DB). Kalau ID-nya terekspos ke sistem eksternal atau URL, hati-hati dengan tabrakan setelah reset

- Constraint foreign key bisa menghalanginya (kebanyakan DB). Kalau subscription mereferensikan customer, kamu perlu mengosongkan tabel anaknya dulu untuk TRUNCATE customer

- Trigger umumnya tidak ter-fire. Trigger adalah mekanisme DB yang otomatis menjalankan SQL sebagai respons terhadap insert / update / delete baris — misalnya, "tulis entri audit log ke tabel lain setiap kali baris dihapus." DELETE memicu trigger ini baris demi baris, tapi TRUNCATE tidak beroperasi di level baris, jadi audit log dan catatan serupa tidak akan dibuat

Gunakan TRUNCATE saat kamu butuh kecepatan maksimal untuk wipe massal data besar; selain itu DELETE WHERE atau DELETE yang bisa di-rollback adalah pilihan yang lebih aman.

QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Mana deskripsi DELETE dan TRUNCATE yang benar?

Soal 2Mana deskripsi terbaik dari High Water Mark (HWM)?

Soal 3Tepat setelah mengosongkan tabel berisi 1 juta baris dengan DELETE FROM tabel; (tanpa WHERE), kamu menjalankan SELECT COUNT(*) FROM tabel;. Mana perilaku yang benar?