↑↓ select↵ open⌫ change scopeOpen full search

PG.CENTER connects PostgreSQL documentation, reference, and ecosystem knowledge. Maintained by Pigsty.

Wiki / Storage Structures

Storage Structures

Version coverage matrix

Definitions for PostgreSQL 18

Reading PG 18·Select a recorded version

35 / 35 recorded definitionsA filled square means the entry is documented in that version. Select one to read it there.
  • Database File LayoutPhysical structures10 – 20

    This section describes the storage format at the level of files and directories.

  • Database Page LayoutPhysical structures10 – 20

    This section provides an overview of the page format used within PostgreSQL tables and indexes. [19] Sequences and TOAST tables are formatted just like a regular table.

  • Free Space MapPhysical structures10 – 20

    Each heap and index relation, except for hash indexes, has a Free Space Map ( FSM ) to keep track of available space in the relation. It's stored alongside the main relation data in a separate relation fork, named after the filenode number of the relation, plus a _fsm suffix. For example, if the filenode of a relation is 12345, the FSM is stored in a file called 12345_fsm , in the same directory as the main relation file.

  • Heap-Only Tuples ( HOT )Physical structures11 – 20

    To allow for high concurrency, PostgreSQL uses multiversion concurrency control ( MVCC ) to store rows. However, MVCC has some downsides for update queries. Specifically, updates require new versions of rows to be added to tables. This can also require new index entries for each updated row, and removal of old versions of rows and their index entries can be expensive.

  • PG_VERSIONPGDATA paths10 – 20

    A file containing the major version number of PostgreSQL

  • TOASTPhysical structures10 – 20

    This section provides an overview of TOAST (The Oversized-Attribute Storage Technique).

  • Table row layoutPhysical structures11 – 20

    Physical row headers, null bitmap, alignment and column data.

  • The Initialization ForkPhysical structures10 – 20

    Each unlogged table, and each index on an unlogged table, has an initialization fork. The initialization fork is an empty table or index of the appropriate type. When an unlogged table must be reset to empty due to a crash, the initialization fork is copied over the main fork, and any other forks are erased (they will be recreated automatically as needed).

  • Visibility MapPhysical structures10 – 20

    Each heap relation has a Visibility Map (VM) to keep track of which pages contain only tuples that are known to be visible to all active transactions; it also keeps track of which pages contain only frozen tuples. It's stored alongside the main relation data in a separate relation fork, named after the filenode number of the relation, plus a _vm suffix. For example, if the filenode of a relation is 12345, the VM is stored in a file called 12345_vm , in the same directory as the main relation file. Note that indexes do not have VMs.

  • WAL InternalsPhysical structures10 – 20

    WAL is automatically enabled; no action is required from the administrator except ensuring that the disk-space requirements for the WAL files are met, and that any necessary tuning is done (see Section 28.5 ).

  • basePGDATA paths10 – 20

    Subdirectory containing per-database subdirectories

  • current_logfilesPGDATA paths10 – 20

    File recording the log file(s) currently written to by the logging collector

  • fsm forkRelation forks10 – 20

    Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index's filenode number, which can be found in pg_class . relfilenode . But for temporary relations, the file name is of the form t BBB _ FFF , where BBB is the process number of the backend which created the file, and FFF is the filenode number. In either case, in addition to the main file (a/k/a main fork), each table and index has a free space map (see Section 66.3 ), which stores information about free space available in the relation. The free space map is stored in a file named with the filenode number plus the suffix _fsm . Tables also have a visibility map , stored in a fork with the suffix _vm , to track which pages are known to have no dead tuples. The visibility map is described further in Section 66.4 . Unlogged tables and indexes have a third fork, known as the initialization fork, which is stored in a fork with the suffix _init (see Section 66.5 ). When a table or index exceeds 1 GB, it is divided into gigabyte-sized segments . The first segment's file name is the same as the filenode; subsequent segments are named filenode.1, filenode.2, etc. This arrangement avoids problems on platforms that have file size limitations. (Actually, 1 GB is just the default segment size. The segment size can be adjusted using the configuration option --with-segsize when building PostgreSQL .) In principle, free space map and visibility map forks could require multiple segments as well, though this is unlikely to happen in practice.

  • globalPGDATA paths10 – 20

    Subdirectory containing cluster-wide tables, such as pg_database

  • init forkRelation forks10 – 20

    Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index's filenode number, which can be found in pg_class . relfilenode . But for temporary relations, the file name is of the form t BBB _ FFF , where BBB is the process number of the backend which created the file, and FFF is the filenode number. In either case, in addition to the main file (a/k/a main fork), each table and index has a free space map (see Section 66.3 ), which stores information about free space available in the relation. The free space map is stored in a file named with the filenode number plus the suffix _fsm . Tables also have a visibility map , stored in a fork with the suffix _vm , to track which pages are known to have no dead tuples. The visibility map is described further in Section 66.4 . Unlogged tables and indexes have a third fork, known as the initialization fork, which is stored in a fork with the suffix _init (see Section 66.5 ).

  • main forkRelation forks10 – 20

    Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index's filenode number, which can be found in pg_class . relfilenode . But for temporary relations, the file name is of the form t BBB _ FFF , where BBB is the process number of the backend which created the file, and FFF is the filenode number. In either case, in addition to the main file (a/k/a main fork), each table and index has a free space map (see Section 66.3 ), which stores information about free space available in the relation. The free space map is stored in a file named with the filenode number plus the suffix _fsm . Tables also have a visibility map , stored in a fork with the suffix _vm , to track which pages are known to have no dead tuples. The visibility map is described further in Section 66.4 . Unlogged tables and indexes have a third fork, known as the initialization fork, which is stored in a fork with the suffix _init (see Section 66.5 ). The pg_relation_filepath() function shows the entire path (relative to PGDATA ) of any relation. It is often useful as a substitute for remembering many of the above rules. But keep in mind that this function just gives the name of the first segment of the main fork of the relation — you may need to append a segment number and/or _fsm , _vm , or _init to find all the files associated with the relation.

  • pg_commit_tsPGDATA paths10 – 20

    Subdirectory containing transaction commit timestamp data

  • pg_dynshmemPGDATA paths10 – 20

    Subdirectory containing files used by the dynamic shared memory subsystem

  • pg_logicalPGDATA paths10 – 20

    Subdirectory containing status data for logical decoding

  • pg_multixactPGDATA paths10 – 20

    Subdirectory containing multitransaction status data (used for shared row locks)

  • pg_notifyPGDATA paths10 – 20

    Subdirectory containing LISTEN/NOTIFY status data

  • pg_replslotPGDATA paths10 – 20

    Subdirectory containing replication slot data

  • pg_serialPGDATA paths10 – 20

    Subdirectory containing information about committed serializable transactions

  • pg_snapshotsPGDATA paths10 – 20

    Subdirectory containing exported snapshots

  • pg_statPGDATA paths10 – 20

    Subdirectory containing permanent files for the statistics subsystem

  • pg_stat_tmpPGDATA paths10 – 20

    Subdirectory containing temporary files for the statistics subsystem

  • pg_subtransPGDATA paths10 – 20

    Subdirectory containing subtransaction status data

  • pg_tblspcPGDATA paths10 – 20

    Subdirectory containing symbolic links to tablespaces

  • pg_twophasePGDATA paths10 – 20

    Subdirectory containing state files for prepared transactions

  • pg_walPGDATA paths10 – 20

    Subdirectory containing WAL (Write Ahead Log) files

  • pg_xactPGDATA paths10 – 20

    Subdirectory containing transaction commit status data

  • postgresql.auto.confPGDATA paths10 – 20

    A file used for storing configuration parameters that are set by ALTER SYSTEM

  • postmaster.optsPGDATA paths10 – 20

    A file recording the command-line options the server was last started with

  • postmaster.pidPGDATA paths10 – 20

    A lock file recording the current postmaster process ID (PID), cluster data directory path, postmaster start timestamp, port number, Unix-domain socket directory path (could be empty), first valid listen_address (IP address or * , or empty if not listening on TCP), and shared memory segment ID (this file is not present after server shutdown)

  • vm forkRelation forks10 – 20

    Each table and index is stored in a separate file. For ordinary relations, these files are named after the table or index's filenode number, which can be found in pg_class . relfilenode . But for temporary relations, the file name is of the form t BBB _ FFF , where BBB is the process number of the backend which created the file, and FFF is the filenode number. In either case, in addition to the main file (a/k/a main fork), each table and index has a free space map (see Section 66.3 ), which stores information about free space available in the relation. The free space map is stored in a file named with the filenode number plus the suffix _fsm . Tables also have a visibility map , stored in a fork with the suffix _vm , to track which pages are known to have no dead tuples. The visibility map is described further in Section 66.4 . Unlogged tables and indexes have a third fork, known as the initialization fork, which is stored in a fork with the suffix _init (see Section 66.5 ). When a table or index exceeds 1 GB, it is divided into gigabyte-sized segments . The first segment's file name is the same as the filenode; subsequent segments are named filenode.1, filenode.2, etc. This arrangement avoids problems on platforms that have file size limitations. (Actually, 1 GB is just the default segment size. The segment size can be adjusted using the configuration option --with-segsize when building PostgreSQL .) In principle, free space map and visibility map forks could require multiple segments as well, though this is unlikely to happen in practice.