linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Хранение и формат на диске/relfilenode-forks

kb/storage ── Хранение и формат на диске ── beginner

relfilenode и форки отношения

Каждая таблица и индекс лежит на диске как набор файлов - форков. Главный форк хранит сами данные, _fsm - карту свободного места, _vm - карту видимости, _init - шаблон для нежурналируемых таблиц. Имя файла - это relfilenode, и оно не равно OID после перезаписи таблицы.

view as markdownaka: relfilenode, relation-forks, forks

Таблица в PostgreSQL - это не один файл. Это несколько параллельных файлов, каждый со своей ролью. Их называют форками (forks). Главный форк хранит строки, остальные - служебные карты, которые ускоряют работу.

Найти главный файл таблицы можно из SQL:

sql
SELECT pg_relation_filepath('flights');
-- base/16384/16503

Путь читается так: base/ - каталог обычных баз, 16384 - OID базы, 16503 - relfilenode, имя файла этой таблицы. Конкретные числа у тебя будут другими: OID назначаются по мере создания объектов. Подробнее про путь до базы - в cluster-pgdata.

Четыре форка

ФоркСуффикс файлаЧто хранит
mainнетсами строки таблицы (или записи индекса)
fsm_fsmкарта свободного места по страницам
vm_vmкарта видимости и заморозки
init_initпустой шаблон для нежурналируемых таблиц

Главный форк есть всегда. Остальные появляются по мере надобности. Сразу после CREATE TABLE на диске только главный файл. Карты _fsm и _vm создаются позже - обычно при первом VACUUM или когда серверу понадобится свободное место под вставку. Про эти карты есть отдельные заметки: free-space-map и visibility-map.

sql
-- сразу после CREATE TABLE: только главный форк
SELECT pg_relation_filepath('t');           -- base/16384/24576 (число своё)
-- файлов 24576_fsm и 24576_vm ещё нет
VACUUM t;                                    -- теперь карты появятся

relfilenode - это не OID

У отношения есть OID (внутренний идентификатор в системном каталоге) и relfilenode (имя файла на диске). Поначалу они совпадают. Но команды, которые переписывают таблицу целиком - VACUUM FULL, TRUNCATE, CLUSTER, ALTER TABLE, меняющий тип колонки, - создают новый файл с новым relfilenode и удаляют старый. OID при этом остаётся прежним.

Поэтому в коде, который должен пережить перезапись, ссылаются на OID, а не на имя файла. А pg_relation_filepath() всегда показывает актуальный relfilenode, считывая его из каталога.

Сегменты по гигабайту

Один форк не растёт одним бесконечным файлом. Когда главный форк переваливает за 1 ГБ, PostgreSQL продолжает в файле relfilenode.1, затем relfilenode.2 и так далее. Это упрощает жизнь старым файловым системам с лимитом на размер файла и операциям копирования. Для тебя как читателя это значит: большая таблица на диске - это пачка файлов 16385, 16385.1, 16385.2, а не один гигантский.

Зачем это знать

Когда видишь в base/16384/ россыпь файлов с суффиксами и номерами, это не хаос, а форки и сегменты конкретных таблиц. Размер _fsm и _vm крошечный по сравнению с главным форком, но именно они позволяют вставке не сканировать таблицу в поисках места, а вакууму - пропускать страницы, где всё уже видимо.

§ команды

bash
SELECT pg_relation_filepath('flights');

Путь к главному форку таблицы относительно PGDATA

bash
SELECT relname, relfilenode, oid FROM pg_class WHERE relname = 'flights';

Сравнить OID и relfilenode отношения (после VACUUM FULL разойдутся)

bash
SELECT pg_relation_size('flights', 'fsm');

Размер форка _fsm в байтах (0, если ещё не создан)

bash
SELECT pg_table_size('flights'), pg_total_relation_size('flights');

Размер таблицы со всеми форками и с индексами

§ см. также

  • cluster-pgdataКластер, PGDATA и каталогиКластер PostgreSQL - это один каталог на диске (PGDATA) и один набор процессов, обслуживающий сразу несколько баз. Внутри PGDATA лежат base/ с данными баз, global/ с общими объектами, pg_wal/ с журналом и служебные каталоги вроде pg_xact/. Всё хранение начинается отсюда.
  • free-space-mapFree Space Map (карта свободного места)Карта свободного места (_fsm) хранит для каждой страницы таблицы, сколько в ней свободно места, с точностью до 32 байт. По ней вставка быстро находит страницу с достаточным зазором, не сканируя таблицу. Карту обновляет VACUUM; у крошечных таблиц её может не быть вовсе.
  • visibility-mapVisibility Map (карта видимости)Карта видимости (_vm) держит по два бита на страницу: all-visible (все строки видны всем) и all-frozen (все строки заморожены). Первый бит позволяет index-only scan не ходить в таблицу за проверкой видимости, а вакууму - пропускать страницу. Биты ставит VACUUM и сбрасывает любая запись в страницу.
  • page-layoutРаскладка страницы 8 КБТаблица на диске - это массив страниц по 8 КБ. Внутри страницы четыре зоны: заголовок 24 байта, массив указателей строк (растёт сверху вниз), свободное место и сами кортежи (растут снизу вверх). У heap-страницы спецзона в конце пустая. Указатели и кортежи движутся навстречу.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки