lesson ── postgres-labs ── ~22 мин ── 5 шагов
Прочитай сырую страницу таблицы и назови её зоны - не из учебника, а из вывода pageinspect. Перед каждым шагом предсказывай: сколько будет указателей, чему равен lower.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
Расширение pageinspect даёт функции для чтения сырых страниц.
CREATE EXTENSION IF NOT EXISTS pageinspect;
✓ Линза установлена - можно вскрывать страницы.
Предскажи число строк на странице 0 таблицы flights, потом проверь.
SELECT count(*) FROM heap_page_items(get_raw_page('flights', 0));Таблица flights небольшая и помещается в одну страницу.
✓ 50 строк - значит, 50 указателей в начале страницы.
Заголовок занимает 24 байта, дальше по 4 байта на указатель. Посчитай
lower = 24 + 50 × 4 и сверь.
SELECT lower, upper, special FROM page_header(get_raw_page('flights', 0));lower - смещение конца массива указателей.
✓ lower = 224 = 24 + 50 × 4. Указатели заняли ровно столько.
У heap-страницы спецзона в конце пустая, поэтому special совпадает с размером страницы. Проверь.
SELECT special, pagesize FROM page_header(get_raw_page('flights', 0));✓ special = 8192 = размер страницы: спецзона пуста.
Указатели нумеруются по возрастанию, а их смещения lp_off убывают: кортежи кладутся с конца страницы вверх. Проверь, что у первого указателя смещение больше, чем у второго.
SELECT lp, lp_off, lp_len
FROM heap_page_items(get_raw_page('flights', 0)) ORDER BY lp LIMIT 5;✓ lp_off убывает - кортежи растут от конца страницы вверх.
Страница heap - это заголовок (24 байта), массив указателей, свободное место и кортежи. lower = 24 + число_строк × 4, special равен pagesize у heap, а кортежи заполняют страницу с конца (lp_off убывает).
команды
CREATE EXTENSION pageinspect;включить линзы страницSELECT * FROM page_header(get_raw_page('t',0));заголовок страницыSELECT * FROM heap_page_items(get_raw_page('t',0));указатели и кортежи страницыконцепции