Skip to content

PostgreSQL 13 – Autovacuum can now be triggered based on inserts

A common issue with insert only tables in PostgreSQL is, that autovacuum well never kick in as the formula for autovacuum considers obsoleted tuples since the last vacuum but not the number of inserted tuples. Because of this you usually run a manual vacuum when a table is bulk loaded right after the load or you schedule regular vacuums for tables you know are insert only. PostgreSQL 13 will finally solve that issue because autovacuum will now be also triggered based on the amount of inserts into a table (more on the exact formula below). As usual let’s do a small, reproducible, demo to see how that works.

I have the latest (as of today) PostgreSQL development version running in the default configuration, except for some logging parameters I usually change. The table I’ll be playing with is this one:

postgres=# create table t1 ( a int, b text, c date );
CREATE TABLE
postgres=# d t1
                 Table "public.t1"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 a      | integer |           |          | 
 b      | text    |           |          | 
 c      | date    |           |          | 

When I bulk load that table in PostgreSQL before 13, autovacuum will never kick in. With PostgreSQL 13 we have two new configuration parameters that control autovacuum when it comes to inserts:

postgres=# show autovacuum_vacuum_insert_threshold;
 autovacuum_vacuum_insert_threshold 
------------------------------------
 1000
(1 row)

postgres=# show autovacuum_vacuum_insert_scale_factor;
 autovacuum_vacuum_insert_scale_factor 
---------------------------------------
 0.2
(1 row)

postgres=# 

The formula is:

vacuum insert threshold = autovacuum_vacuum_insert_threshold + autovacuum_vacuum_insert_scale_factor * number of tuples

When we start with an empty table autovacuum should kick in when we insert more than 1000 rows:

postgres=# insert into t1 (a,b,c) select i, i::text, now() from generate_series(1,1001) i;
INSERT 0 1001

Wait some time (autovacuum_naptime is 1 minute in the default configuration, so this is the maximum you will need to wait) and check pg_stat_user_tables for the last autovacuum:

postgres=# select last_autovacuum, autovacuum_count from pg_stat_user_tables where relname = 't1';
       last_autovacuum        | autovacuum_count 
------------------------------+------------------
 2020-03-29 15:25:42.75171+02 |                1
(1 row)

Perfect, that works. This is really a great improvement as you do not need to take special care of mostly insert only tables that do not receive a lot of updates or deletes. In addition you can probably skip all the manual vacuums after bulk loading.

Let’s work together

Ready to operate at
the next level?

Tell us about your challenge. We’ll bring the depth, the expertise, and the Swiss precision.

Open source Team

Open source Team

Posts published under the Open source Team account are collective contributions by the dbi services open infrastructure consultants. The practice covers open-source databases and platforms, PostgreSQL first of all, along with MySQL, MariaDB, and Linux, from architecture, replication, and high availability to performance tuning and operations under service level agreements, and contributes actively to the PostgreSQL community.View Author posts

721 posts since September 2011

Most read in Database

The Database posts our readers open most: the all-time favourites, and what is trending right now.

Leave a Comment

Your email address will not be published. Required fields are marked *