Skip to main content
Disk space utilization
Last update:

Disk space utilization

PostgreSQL cluster disks store:

  • temporary files;
  • data files;
  • transaction logs (WALs);
  • logical replication slots;
  • DBMS logs;
  • system files required for PostgreSQL to function.

You can monitor the amount of disk space used.

When the amount of disk space used grows, you can check:

If the cluster disk is 80% full, a notification will appear in the dashboard and will be sent to the email of the Account Owner and those users subscribed to the Notification category Services and services.

If the cluster disk is 95% or more full, the cluster will go into status DISK_FULL and will be read-only. To make the cluster read-write, disk cleanup or scale the cluster and select a configuration with a larger disk size.

View the size of temporary files

Temporary files can be used for sorting, hashing, and temporarily storing query results. To see the total size of temporary files in the database, use SQL query to the view pg_stat_database:

SELECT datname, temp_files AS "Temporary files", temp_bytes AS "Size of temporary files"
FROM pg_stat_database;

Example output:

datname | temp_files   | temp_bytes
--------+--------------+----------------
mydb | 2 | 16384
postgres| 1 | 8192

Here:

  • datname — database name;
  • temp_files — the number of temporary files in this database;
  • temp_bytes — size of temporary files in bytes.

In the fields temp_files and temp_bytes All temporary files since the cluster was created are taken into account. Data is only reset after restoring from backup or after a disaster. Use the values of these fields to monitor changes in the total size of temporary files.

The size of temporary tables created by a specific query can be obtained using the command ANALYZE.

Check consumers of logical replication slots

Logical replication slots are used to continuously replicate data from one database to another. Logical replication slots must always have a consumer. If there is no consumer, the file size will grow.

Read more about managing logical replication slots in the article Subscription PostgreSQL documentation.

To check if logical replication slots have consumers, send an SQL query to the view pg_replication_slots:

SELECT slot_name, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS replicationSlotLag,active
FROM pg_replication_slots;

Example output:

slot_name        | replicationslotlag | active
-----------------+--------------------+--------
myslot1 | 129 GB | f
myslot2 | 704 MB | t
myslot3 | 624 MB | t

Here:

  • slot_name — name of the logical replication slot;
  • replicationslotlag — the size of WAL files that will not be automatically deleted at checkpoints and that consumers of the logical replication slot can use;
  • active — boolean value indicates whether the logical replication slot is in use:
    • f — the slot doesn't have a consumer;
    • t — the slot has a consumer.

If you have PostgreSQL version 13 or higher, you can limit the maximum size of stored WAL files using the parameter max_slot_wal_keep_size. Note that when using this option, the transaction log may be deleted before the consumer reads the changes from the logical replication slot.

"Dead" motorcades

When you update rows in a table (UPDATE) or delete them (DELETE), tuples are not actually deleted from disk, but new versions of them are created. The old versions of tuples will be called "dead tuples". This versioning is necessary to implement the process MVCC (Multi-Version Concurrency Control). Even though the rows are changed in one transaction, other active transactions may continue to see the old version of the rows. "Dead" tuples can only be deleted when all active transactions are closed.

"Dead" tuples will also be formed on the replica if you are using logical replication.

Check for "dead" tuples

If there are many dead tuples, they can take up a significant amount of disk space. To check the number of "dead" tuples, use the following view pg_stat_all_tables.

Example of an SQL query for a view pg_stat_all_tables:

SELECT * FROM pg_stat_all_tables WHERE relname='test';

Example output:

-[ RECORD 1 ]----------+------------------------------
relid | 16395
schemaname | public
relname | test
seq_scan | 3
seq_tup_read | 5280041
idx_scan |
idx_tup_fetch |
n_tup_ins | 2000000
n_tup_upd | 0
n_tup_del | 3639911
n_tup_hot_upd | 0
n_live_tup | 1635941
n_dead_tup | 1999952
n_mod_since_analyze | 3999952
last_vacuum |
last_autovacuum | 2023-02-16 04:49:52.399546+00
last_analyze | 2023-02-09 09:44:56.208889+00
last_autoanalyze | 2023-02-16 04:50:22.581935+00
vacuum_count | 0
autovacuum_count | 1
analyze_count | 1
autoanalyze_count | 1

Here. n_dead_tup — the number of "dead" tuples.

Delete "dead" tuples

To remove "dead" tuples, use the VACUUM operation or configure AUTOVACUUM. These operations remove unused versions of rows in tables and indexes and mark the space free for future use. However, this disk space is not returned to the operating system except in the special case where one or more pages at the end of a table are completely free and an exceptional table lock can be obtained. Read more about VACUUM and AUTOVACUUM operations in the article Routine Vacuuming PostgreSQL documentation.

Clear the disk

Open a transaction transaction_read_only = no and delete unnecessary data using one of the queries:

  • DROP TABLE — deletes the structure (data, privileges, indexes, constraints, triggers). Use when completely deleting a table with data and structure:

    BEGIN;
    SET transaction_read_only = no;
    DROP TABLE table_name;
    COMMIT;
  • TRUNCATE TABLE — deletes the contents of the table, but the structure is preserved. Works faster DROP TABLE. Use when deleting all rows of a table while preserving the table structure:

    BEGIN;
    SET transaction_read_only = no;
    TRUNCATE TABLE table_name;
    COMMIT;
  • DELETE — use to delete specific strings.

For your information

We do not recommend using the query DELETE FROM table WHERE ... to clean up the disk. This query can create oversized samples on large tables and place them on disk. The remaining free disk space may run out completely, causing problems with PostgreSQL and the need to restore its operation manually.