lesson ── postgres-labs ── ~22 мин ── 6 шагов
Пройди путь от имени таблицы до её файлов и понаблюдай, как форки появляются, а relfilenode меняется. Перед каждым шагом предсказывай: нулевой ли размер форка, совпадут ли OID и relfilenode.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
Найди файл таблицы flights и разбери путь на OID базы и relfilenode.
SELECT pg_relation_filepath('flights');✓ Путь base/<oid>/<relfilenode> найден.
Создай таблицу и наполни её, чтобы было что вакуумить.
CREATE TABLE forklab (id int, note text);
INSERT INTO forklab SELECT g, 'row'||g FROM generate_series(1, 300) g;
✓ 300 строк на месте.
Предскажи размер форка _vm до первого VACUUM. Карту видимости
заполняет именно VACUUM, поэтому сейчас её может ещё не быть.
SELECT pg_relation_size('forklab', 'vm');Форк появляется лениво. Нет файла - размер 0.
✓ Карты видимости пока нет - её размер 0.
Сравни внутренний идентификатор и имя файла. Сейчас они равны.
SELECT oid, relfilenode, oid = relfilenode AS same
FROM pg_class WHERE relname = 'forklab';
✓ Пока OID и relfilenode совпадают.
Выполни вакуум и снова посмотри размер _vm. Предскажи: станет ли он
ненулевым?
VACUUM forklab;
SELECT pg_relation_size('forklab', 'vm');✓ После VACUUM форк _vm появился - его размер больше 0.
Перепиши таблицу целиком и снова сравни OID с relfilenode. Объясни, почему OID тот же, а relfilenode другой.
VACUUM FULL forklab;
SELECT oid, relfilenode, oid = relfilenode AS same
FROM pg_class WHERE relname = 'forklab';
VACUUM FULL переписывает таблицу в новый файл - имя файла меняется, идентификатор нет.
✓ relfilenode сменился, OID прежний - таблицу переписали в новый файл.
Таблица - это набор форков: главный, _fsm, _vm. Карту видимости _vm заполняет VACUUM, поэтому до него её размер 0. relfilenode - имя файла, меняется при перезаписи (VACUUM FULL), а OID остаётся постоянным.
команды
SELECT pg_relation_filepath('t');путь к главному форкуSELECT pg_relation_size('t','vm');размер карты видимостиSELECT oid, relfilenode FROM pg_class WHERE relname='t';идентификатор против имени файлаконцепции