Tidbits on software development, technology, and other geeky stuff

Batch Deletes in Postgres

If you need to delete many, many rows in a Postgres table, issuing a single DELETE statement can be problematic for a few reasons:

To work around these issues, you can delete rows in batches. There are various ways to do this but I prefer the following approach, using a DELETE ... WHERE ... IN (SELECT ... LIMIT) query with a \watch command in psql.

First, construct a delete query using a WHERE .. IN statement and a LIMIT to ensure only a batch of records are deleted. Here’s an example that deletes 1,000 rows from a table named my_table where the created_at column is older than 30 days:

DELETE FROM my_table
WHERE id IN (
  SELECT id
  FROM my_table
  WHERE created_at < now() - interval '30 days'
  -- Delete only 1000 rows at a time
  LIMIT 1000
);

Execute this query within psql and ensure it completes without error.

Now, run \watch 1 within psql. This will re-run the last query every second and display the number of rows deleted.

After a few seconds, you should see output like this:

DELETE 1000
DELETE 1000
DELETE 1000

This indicates that 1,000 rows are being deleted every second.

When all rows have been deleted, you will see output like this:

DELETE 0
DELETE 0
DELETE 0

Since all rows have been deleted at this point, you can stop the watch command with CTRL+C in psql.

Discuss on Twitter