TOAST
PostgreSQL позволяет хранить большие данные с помощью, например, типов text или jsonb. Если итоговая строка не помещается в страницу Базы (~8 КБ), PostgreSQL попытается уменьшить её размер — сжать и если этого не хватит, БД разбивает значение на фрагменты (по ~1996 байт (~2 КБ) - это размер позволяющий гарантированно поместить фрагмент в страницу) и сохраняет эти фрагменты в отдельную TOAST‑таблицу, которая создаётся автоматически. В основной строке (куда было бы помещено простое значение) сохраняется ссылка (TOAST-указатель, а не сами данные). Когда данные запрашиваются PostgreSQL по ссылке получает фрагменты и снова собирает их.
Особенности:
- TOAST-таблица — это обычная таблица с полями:
chunk_id,chunk_seq,chunk_data - Механизм автоматический, включается когда строка превышает допустимый размер
- Есть несколько стратегий сжатия и хранения (
PLAIN,EXTENDED,EXTERNAL,MAIN). По умолчанию используетсяEXTENDED: сначала База попытается сжать данные, после чего при необходимости значение может быть вынесено в TOAST - Чтение TOAST‑данных немного дороже, чем чтение обычных (надо задействовать дополнительную таблицу и собирать фрагменты). Но это уменьшает размер основной таблицы и сокращает объём данных, который PostgreSQL читает при работе со строками без больших значений
- Статистика для больших полей может быть менее точной, так как при анализе используются усечённые значения
- Большие значения извлекаются только при обращении к ним (как lazy load)
-- Если есть TOAST то будет две строки — основная таблица и её TOAST-таблица
SELECT c.relname AS table_name,
c.relpages,
c.reltuples,
pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size
FROM pg_class c
WHERE c.oid = 'table_name'::regclass
OR c.oid = (
SELECT reltoastrelid
FROM pg_class
WHERE oid = 'table_name'::regclass
);