How to Use the Concurrency-Related Parameters in PostgreSQL

Modern storage devices such as SSDs and NVMe drives are capable of processing multiple input/output requests simultaneously. PostgreSQL provides several configuration parameters that allow it to take advantage of this capability, improving query execution and maintenance performance. Also in PostgreSQL version 18, we have the feature of asynchronous input/output, and new parameters like io_workers are introduced.

Whenever Postgres needs to read data from disk, it can either issue one request at a time or multiple requests simultaneously.

If the underlying storage supports concurrent I/O (which most SSDs and SAN storage do), Postgres can prefetch multiple blocks at once, reducing wait time and improving overall performance.

These parameters control different aspects of that behavior.

Let’s check each parameter one by one.

show effective_io_concurrency ;

Result:

 effective_io_concurrency 
--------------------------
 16
(1 row)

Check the metadata from pg_settings like this.

select * from pg_settings where name = 'effective_io_concurrency';

Result:

-[ RECORD 1 ]---+---------------------------------------------------------------------------------------
name            | effective_io_concurrency
setting         | 16
unit            | 
category        | Resource Usage / I/O
short_desc      | Number of simultaneous requests that can be handled efficiently by the disk subsystem.
extra_desc      | 0 disables simultaneous requests.
context         | user
vartype         | integer
source          | default
min_val         | 0
max_val         | 1000
enumvals        | 
boot_val        | 16
reset_val       | 16
sourcefile      | 
sourceline      | 
pending_restart | f

This is the parameter definition from the guc_parameters.dat file.

{ name => 'effective_io_concurrency', type => 'int', context => 'PGC_USERSET', group => 'RESOURCES_IO',
  short_desc => 'Number of simultaneous requests that can be handled efficiently by the disk subsystem.',
  long_desc => '0 disables simultaneous requests.',
  flags => 'GUC_EXPLAIN',
  variable => 'effective_io_concurrency',
  boot_val => 'DEFAULT_EFFECTIVE_IO_CONCURRENCY',
  min => '0',
  max => 'MAX_IO_CONCURRENCY',
},

The effective_io_concurrency parameter tells the postgres that how many disk read operations it can try to perform at the same time. It helps the postgres to make better use of storage devices that support multiple simultaneous I/O requests, such as SSDs and NVMe drives.

A higher value can improve the performance of operations like bitmap heap scans by allowing PostgreSQL to prefetch more data from disk. Setting it to 0 disables concurrent I/O requests.

Check the default value of the parameter named io_max_concurrency.

show io_max_concurrency ;

Result:

 io_max_concurrency 
--------------------
 64
(1 row)

Check the metadata from pg_settings like this.

select * from pg_settings where name = 'io_max_concurrency';

Result:

-[ RECORD 1 ]---+---------------------------------------------------------------
name            | io_max_concurrency
setting         | 64
unit            | 
category        | Resource Usage / I/O
short_desc      | Max number of IOs that one process can execute simultaneously.
extra_desc      | 
context         | postmaster
vartype         | integer
source          | default
min_val         | -1
max_val         | 1024
enumvals        | 
boot_val        | -1
reset_val       | 64
sourcefile      | 
sourceline      | 
pending_restart | f

Check the parameter definition in the file named guc_parameters.dat file.

{ name => 'io_max_concurrency', type => 'int', context => 'PGC_POSTMASTER', group => 'RESOURCES_IO',
  short_desc => 'Max number of IOs that one process can execute simultaneously.',
  variable => 'io_max_concurrency',
  boot_val => '-1',
  min => '-1',
  max => '1024',
  check_hook => 'check_io_max_concurrency',
},

The io_max_concurrency parameter specifies the maximum number of I/O operations that a single Postgres process can perform at the same time. It helps control the level of concurrent disk I/O, preventing a backend process from issuing too many requests simultaneously.

This parameter is set when the server starts, so changing it requires a restart of the Postgres server.

Check the default value of this parameter like this.

show maintenance_io_concurrency;

Result:

 maintenance_io_concurrency 
----------------------------
 0
(1 row)

Check the metadata from pg_settings like this.

select * from pg_settings where name = 'maintenance_io_concurrency';

Result:

-[ RECORD 1 ]---+---------------------------------------------------------------------------
name            | maintenance_io_concurrency
setting         | 0
unit            | 
category        | Resource Usage / I/O
short_desc      | A variant of "effective_io_concurrency" that is used for maintenance work.
extra_desc      | 0 disables simultaneous requests.
context         | user
vartype         | integer
source          | configuration file
min_val         | 0
max_val         | 1000
enumvals        | 
boot_val        | 16
reset_val       | 0
sourcefile      | /var/lib/postgresql/18/main/postgresql.auto.conf
sourceline      | 5
pending_restart | f

Look at the parameter definition from the guc_parameters.dat file.

{ name => 'maintenance_io_concurrency', type => 'int', context => 'PGC_USERSET', group => 'RESOURCES_IO',
  short_desc => 'A variant of "effective_io_concurrency" that is used for maintenance work.',
  long_desc => '0 disables simultaneous requests.',
  flags => 'GUC_EXPLAIN',
  variable => 'maintenance_io_concurrency',
  boot_val => 'DEFAULT_MAINTENANCE_IO_CONCURRENCY',
  min => '0',
  max => 'MAX_IO_CONCURRENCY',
  assign_hook => 'assign_maintenance_io_concurrency',
},

The maintenance_io_concurrency parameter specifies how many disk I/O requests that the postgres can perform simultaneously during maintenance operations, such as VACUUM, CREATE INDEX, REINDEX, and ANALYZE.

Increasing this value can improve the performance of these operations on storage devices that support concurrent I/O. A value of 0 disables concurrent I/O requests for maintenance tasks.

Postgres provides several parameters to control how it performs concurrent disk I/O operations. While effective_io_concurrency improves read performance during normal query execution, io_max_concurrency limits the number of simultaneous I/O operations that a backend process can issue, and maintenance_io_concurrency applies similar settings to maintenance tasks such as VACUUM, CREATE INDEX, and REINDEX.

Understanding the purpose of these parameters and when to adjust them can help you make better use of modern storage devices and improve overall database performance. Before changing any of these settings, test them in your environment to ensure they provide the expected performance benefits.

WhatsApp