Lob's website experience is not optimized for Internet Explorer.
Please choose another browser.

Arrow Up to go to top of page
Hero Image for Lob Deep Dives Blog PostTRUNCATE vs DELETE: Efficiently Clearing Data from a Postgres TableDirect Mail Q&A's
Engineering
July 29, 2019

TRUNCATE vs DELETE: Efficiently Clearing Data from a Postgres Table

By

Marcus Gartner

Share this post

Understanding how to remove data from a PostgreSQL table can be confusing, especially when comparing the TRUNCATE and DELETE commands. These SQL commands both clear data from tables, but they work in different ways and have different effects.

Choosing between TRUNCATE and DELETE is not only about which command erases records faster. Each command has unique mechanics, impacts on table structure, and transactional behavior. These differences can affect how your database performs and how data changes are tracked.

If you're new to PostgreSQL or SQL, getting familiar with the differences between TRUNCATE and DELETE can help avoid mistakes and ensure that data management tasks run as expected.

Understand the difference between TRUNCATE and DELETE

DELETE works like a precision tool — it targets specific rows one by one. TRUNCATE is more like hitting the reset button — it wipes the entire table clean in one swift move. Because TRUNCATE doesn't process rows individually, it's more efficient for large data purges.

Here's how these PostgreSQL commands differ in their approach:

  • DELETE removes specific rows: You can target certain records using WHERE clauses, making it perfect for your selective data removal needs
  • TRUNCATE clears entire tables: It removes all data without conditions, essentially removing all data and resetting the table to its original empty state
  • DELETE preserves table structure: The table remains exactly as it was, just with fewer (or zero) rows
  • TRUNCATE resets the table: It can restart identity sequences and reclaim storage space immediately

DELETE makes PostgreSQL work harder — scanning every single row to find what to remove. TRUNCATE skips all that legwork and goes straight to clearing the table.

Compare performance between TRUNCATE and DELETE

TRUNCATE crushes DELETE when you're clearing massive amounts of data. The bigger your table, the more dramatic the speed difference becomes.

For small tables with just a handful of rows, DELETE often completes faster. This happens because TRUNCATE has overhead costs that become worthwhile only when processing substantial amounts of data.

Performance breakdown by table size: - Small tables (under 1,000 rows): DELETE usually wins due to lower overhead - Medium tables (1,000-100,000 rows): TRUNCATE starts showing advantages
- Large tables (100,000+ rows): TRUNCATE significantly outperforms DELETE

At Lob, we've measured how TRUNCATE can be slower in testing scenarios when tables are small and cleared repeatedly.

Learn how TRUNCATE and DELETE handle transactions

Here's where things get interesting: both commands play by PostgreSQL's transaction rules, but they handle rollbacks and locks in completely different ways.

In Postgres, TRUNCATE is fully transactional. You can roll it back if the transaction isn't committed yet, restoring the table to its original state. However, TRUNCATE requires an exclusive lock on the table, so concurrent transactions will be blocked until it finishes.

DELETE uses row-level locking, allowing other transactions to continue working with unaffected rows. This makes DELETE more suitable for environments where you can't afford to block table access.

Transaction behavior comparison: - TRUNCATE: Full table lock, but faster execution for complete data removal - DELETE: Row-level locks, allowing concurrent access to other rows - Rollback capability: Both commands can be rolled back within active transactions

Understand the overhead

Want to see what's really happening under the hood? The overhead differences tell the whole story.

TRUNCATE performs these operations: - Deallocates data pages immediately - Optionally resets identity sequences - Updates system catalogs - Releases storage space back to the operating system

DELETE performs these operations: - Scans each row to evaluate WHERE conditions - Marks rows as deleted in the transaction log - Maintains indexes and foreign key relationships - Keeps storage space allocated (requiring VACUUM to reclaim)

We've seen TRUNCATE actually perform slower than DELETE when working with small tables in testing scenarios where you're clearing data repeatedly.

Know when to use TRUNCATE vs DELETE

Knowing when to use TRUNCATE vs DELETE can reduce execution time from minutes to seconds:

Use TRUNCATE when you want to: - Clear all data from large tables quickly - Reset identity sequences to start over - Reclaim disk space immediately - Perform bulk data refreshes or testing scenarios

Use DELETE when you need to: - Remove specific rows based on conditions - Maintain concurrent access to the table - Preserve existing identity sequence values - Work with tables that have foreign key constraints

Both commands have their sweet spot — pick the one that matches your table size, usage patterns, and need for selective data removal.

Handle foreign key constraints

Foreign key relationships create important differences between how TRUNCATE and DELETE behave.

DELETE respects foreign key constraints automatically. If you try to delete a row that other tables reference, PostgreSQL will prevent the operation or cascade the deletion based on your constraint settings.

TRUNCATE table in PostgreSQL requires special handling for foreign keys. You'll get an error if foreign key constraints reference the table you're trying to truncate. You can work around this by:

  • Using TRUNCATE table_name CASCADE to truncate related tables too
  • Temporarily dropping and recreating constraints
  • Using DELETE instead when foreign key relationships are complex

Manage identity sequences and auto-increment columns

Both commands handle auto-increment columns differently, which affects what happens to your primary keys.

When you use TRUNCATE table psql commands, you can control sequence behavior: - TRUNCATE table_name keeps the sequence at its current value - TRUNCATE table_name RESTART IDENTITY resets sequences back to their starting values

DELETE never affects identity sequences. Even if you delete all rows, the next inserted row will continue from where the sequence left off.

This difference matters when you're refreshing data or running tests where you want predictable ID values.

Choose the right command for your PostgreSQL workflow

Choosing between TRUNCATE and DELETE really comes down to what you're trying to accomplish.

For data warehouse operations, ETL processes, and bulk data refreshes, TRUNCATE table in PostgreSQL offers speed and efficiency. For application logic that removes specific records, maintains referential integrity, or allows concurrent access, DELETE provides the precision and safety you need.

At Lob, we use both commands strategically. TRUNCATE helps us quickly reset large datasets during testing and data pipeline operations. DELETE handles precise record removal in our production systems where maintaining data relationships and concurrent access is critical.

Quick decision framework:

  • Need to clear everything? Consider TRUNCATE for speed
  • Need to be selective? Use DELETE for precision
  • Have foreign keys? DELETE handles constraints automatically
  • Want to reset sequences? TRUNCATE with RESTART IDENTITY does this
  • Need concurrent access? DELETE allows other transactions to continue
FAQs
Frequently Asked Questions about TRUNCATE and DELETE in PostgreSQL

What is the main difference between TRUNCATE and DELETE in PostgreSQL?

TRUNCATE removes all rows at once and reclaims space immediately, making it fast for large tables. DELETE processes rows individually and lets you choose specific rows to remove, making it slower for large datasets but more precise for targeted operations.

Does TRUNCATE reset auto-increment primary keys in PostgreSQL?

Yes, but only if you use the RESTART IDENTITY option. TRUNCATE table_name RESTART IDENTITY resets sequences to start from 1 again, while TRUNCATE table_name alone keeps the sequence at its current value.

When should you use TRUNCATE instead of DELETE in PostgreSQL?

Use TRUNCATE when you want to remove all rows from a table quickly, especially with large datasets. It's particularly useful for clearing staging tables, resetting test data, or performing bulk data refreshes where you don't need to preserve any existing rows.

Can you roll back TRUNCATE and DELETE operations in PostgreSQL?

Both TRUNCATE and DELETE can be rolled back within active transactions in PostgreSQL. However, TRUNCATE requires an exclusive table lock, while DELETE uses row-level locking, affecting how other transactions can access the table during the operation.

Answered by:

Continue Reading