← На главную

PostgreSQL: OID, 8K страницы и TOAST для больших значений

29.06.2026 12:59 · hackernews

PostgreSQL хранит данные в кластере — это одна инстанция базы, а не несколько серверов. У каждого объекта внутри есть уникальный идентификатор — Oid, целое число без знака. Встроенные объекты получают низкие OID (1, 4, 5 для баз template1, template0, postgres), а пользовательские начинаются с 16384. Системные каталоги — обычные таблицы вроде pg_database, pg_class, pg_index. Каталог pg_database один на весь кластер, остальные — на каждую базу отдельно. Раньше каждая строка в таблице имела OID, но начиная с PostgreSQL 12 эта возможность полностью убрана.

Физически всё лежит в директории, которую указывает переменная PGDATA — обычно /var/lib/pgsql/data или аналог. Внутри $PGDATA/base/ лежат поддиректории баз, названные их OID. Таблицы и индексы — файлы внутри этих папок, их имена задаёт relfilenode. После создания таблицы OID и relfilenode совпадают, но после VACUUM FULL relfilenode меняется, а OID остаётся навсегда. Размер страницы — 8192 байта, меняется только перекомпиляцией. В странице есть заголовок, массив line pointers (указатели на кортежи), сами кортежи (строки) и свободное место. Кортежи добавляются с конца страницы, line pointers — с начала.

Для больших значений PostgreSQL использует TOAST. Если строка превышает 2 КБ, данные сжимаются и выносятся в отдельную TOAST-таблицу. В исходной таблице остаётся только 18-байтовый указатель (varatt_external) с размером, идентификатором значения и ссылкой на TOAST-таблицу. Сама TOAST-таблица — обычная таблица со столбцами chunk_id, chunk_seq и chunk_data (bytea). Данные разбиваются на чанки по 1996 байт, порядок собирается по chunk_seq.

При вставке строк Postgres обновляет указатели pd_lower (конец line pointers) и pd_upper (начало кортежей), выравнивая данные по 8 байтам. При чтении возможен последовательный скан всех страниц или индексный доступ — по умолчанию B-tree. Расширение pageinspect позволяет заглянуть внутрь страниц и увидеть все эти механизмы вживую. Статья — первая из серии заметок автора по книге «The Internals of PostgreSQL».

Читать оригинал →