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/Хранение и формат на диске/free-space-map

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

Free Space Map (карта свободного места)

Карта свободного места (_fsm) хранит для каждой страницы таблицы, сколько в ней свободно места, с точностью до 32 байт. По ней вставка быстро находит страницу с достаточным зазором, не сканируя таблицу. Карту обновляет VACUUM; у крошечных таблиц её может не быть вовсе.

view as markdownaka: fsm, freespace

Когда нужно вставить строку, PostgreSQL должен найти страницу, где она поместится. Сканировать ради этого всю таблицу было бы дорого. Поэтому у каждой таблицы есть карта свободного места - отдельный форк _fsm (см. relfilenode-forks), который для каждой страницы помнит размер свободного зазора.

Грубо, но быстро

Карта хранит свободное место не побайтово, а категориями: диапазон 8 КБ делится на 256 ступеней по 32 байта, и для страницы пишется одна ступень (0-255). Точность в 32 байта тут не вредит: вставке не нужно знать свободное место до байта, ей хватает «влезет / не влезет». Зато вся карта получается крошечной - один байт на страницу данных.

Внутри _fsm ступени уложены деревом, поэтому запрос «дай страницу, где свободно хотя бы N байт» отвечается за пару обращений, а не перебором.

Как это выглядит

Расширение pg_freespacemap показывает карту в байтах свободного места на страницу:

sql
CREATE EXTENSION IF NOT EXISTS pg_freespacemap;
VACUUM bloat_demo;
SELECT blkno, avail FROM pg_freespace('bloat_demo') ORDER BY blkno LIMIT 5;
--  blkno | avail
-- -------+-------
--      0 |  8160
--      1 |  8160

avail - сколько байт свободно на странице по версии карты. У bloat_demo половина версий мертва после массового UPDATE; вакуум убрал их с первых страниц, и те освободились почти целиком (8160 - это пустая страница за вычетом заголовка). Заметь: число округлено до кратного 32.

Кто и когда обновляет карту

Главный поставщик данных для карты - VACUUM. Пройдясь по таблице и убрав мёртвые версии, он записывает в _fsm, сколько места освободилось на каждой странице. Обычная вставка тоже подправляет карту, когда занимает место. Карта приблизительная: она может слегка отставать от реальности, и это нормально - перед вставкой сервер всё равно перепроверяет саму страницу.

Если карта говорит, что свободной страницы нет, таблица расширяется - в конец дописывается новая пустая страница.

Почему её иногда нет

Сразу после CREATE TABLE форка _fsm не существует - он появляется позже, обычно при первом вакууме. У совсем маленьких таблиц (несколько страниц) карты может не быть вообще: проверить три страницы напрямую дешевле, чем заводить и поддерживать карту. Поэтому pg_relation_size('t', 'fsm') для свежей маленькой таблицы вернёт 0.

§ команды

bash
CREATE EXTENSION IF NOT EXISTS pg_freespacemap;

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

bash
SELECT blkno, avail FROM pg_freespace('bloat_demo') ORDER BY blkno;

Свободные байты на каждой странице по версии карты

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

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

§ см. также

  • relfilenode-forksrelfilenode и форки отношенияКаждая таблица и индекс лежит на диске как набор файлов - форков. Главный форк хранит сами данные, _fsm - карту свободного места, _vm - карту видимости, _init - шаблон для нежурналируемых таблиц. Имя файла - это relfilenode, и оно не равно OID после перезаписи таблицы.
  • visibility-mapVisibility Map (карта видимости)Карта видимости (_vm) держит по два бита на страницу: all-visible (все строки видны всем) и all-frozen (все строки заморожены). Первый бит позволяет index-only scan не ходить в таблицу за проверкой видимости, а вакууму - пропускать страницу. Биты ставит VACUUM и сбрасывает любая запись в страницу.
  • page-layoutРаскладка страницы 8 КБТаблица на диске - это массив страниц по 8 КБ. Внутри страницы четыре зоны: заголовок 24 байта, массив указателей строк (растёт сверху вниз), свободное место и сами кортежи (растут снизу вверх). У heap-страницы спецзона в конце пустая. Указатели и кортежи движутся навстречу.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки