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

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

Visibility Map (карта видимости)

Карта видимости (_vm) держит по два бита на страницу: all-visible (все строки видны всем) и all-frozen (все строки заморожены). Первый бит позволяет index-only scan не ходить в таблицу за проверкой видимости, а вакууму - пропускать страницу. Биты ставит VACUUM и сбрасывает любая запись в страницу.

view as markdownaka: vm-fork, all-visible

У версионной базы есть неприятная цена: чтобы понять, видна ли строка, обычно нужно прочитать её заголовок и проверить транзакционные поля. Карта видимости - форк _vm (см. relfilenode-forks) - даёт срезку для целых страниц: если на странице заведомо всё видимо, проверять каждую строку не нужно.

Два бита на страницу

БитСмысл
all-visibleкаждая строка на странице видна всем транзакциям
all-frozenкаждая строка на странице заморожена

Бит all-visible означает: все версии на странице зафиксированы, давно видимы и нет мёртвых, ждущих уборки. Бит all-frozen - более сильное утверждение: версии не просто видимы, а заморожены, и их возраст уже не важен.

Посмотреть биты по страницам:

sql
CREATE EXTENSION IF NOT EXISTS pg_visibility;
VACUUM (FREEZE) flights;
SELECT blkno, all_visible, all_frozen
FROM pg_visibility('flights') ORDER BY blkno LIMIT 3;
--  blkno | all_visible | all_frozen
-- -------+-------------+------------
--      0 | t           | t

Зачем бит all-visible: index-only scan

Главный выигрыш - index-only scan. Индекс хранит значения колонок, но не хранит, видима ли строка конкретной транзакции. Поэтому обычно после поиска по индексу приходится сходить в таблицу и проверить видимость строки. Но если страница помечена all-visible, проверять нечего: всё на ней видно всем. Тогда сервер берёт данные прямо из индекса и в таблицу не идёт. Поэтому свежий VACUUM часто превращает обычный indexed-доступ в более быстрый index-only.

Зачем бит all-frozen: пропуск при вакууме

Заморозка и борьба с переполнением счётчика транзакций требуют иногда проходить таблицу целиком. Бит all-frozen позволяет такому проходу пропускать страницы, где всё уже заморожено, - а это почти вся append-only таблица. Без карты каждый агрессивный вакуум перечитывал бы всю историю заново.

Когда биты сбрасываются

Любая запись в страницу - INSERT, UPDATE, DELETE - сбрасывает оба бита: теперь на странице есть свежая версия, чью видимость надо проверять. Поставить биты обратно может только VACUUM. Поэтому на активно изменяемой таблице доля all-visible страниц всё время скачет, а на редко меняемой держится у 100%.

§ команды

bash
CREATE EXTENSION IF NOT EXISTS pg_visibility;

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

bash
SELECT blkno, all_visible, all_frozen FROM pg_visibility('flights');

Биты видимости и заморозки по каждой странице таблицы

bash
SELECT * FROM pg_visibility_map_summary('flights');

Сводка: сколько страниц all-visible и all-frozen

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

Размер форка _vm в байтах

§ см. также

  • relfilenode-forksrelfilenode и форки отношенияКаждая таблица и индекс лежит на диске как набор файлов - форков. Главный форк хранит сами данные, _fsm - карту свободного места, _vm - карту видимости, _init - шаблон для нежурналируемых таблиц. Имя файла - это relfilenode, и оно не равно OID после перезаписи таблицы.
  • free-space-mapFree Space Map (карта свободного места)Карта свободного места (_fsm) хранит для каждой страницы таблицы, сколько в ней свободно места, с точностью до 32 байт. По ней вставка быстро находит страницу с достаточным зазором, не сканируя таблицу. Карту обновляет VACUUM; у крошечных таблиц её может не быть вовсе.
  • page-layoutРаскладка страницы 8 КБТаблица на диске - это массив страниц по 8 КБ. Внутри страницы четыре зоны: заголовок 24 байта, массив указателей строк (растёт сверху вниз), свободное место и сами кортежи (растут снизу вверх). У heap-страницы спецзона в конце пустая. Указатели и кортежи движутся навстречу.
  • tuple-headerЗаголовок кортежаПеред данными каждой строки лежит служебный заголовок в 23 байта, выровненный до 24. В нём t_xmin и t_xmax (кто вставил и кто удалил версию), t_ctid (ссылка на себя или на новую версию), t_infomask с флагами и t_hoff - смещение до пользовательских данных. Это поля, на которых стоит весь MVCC.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки