MATERIALIZED VIEW

Тема дорожной карты · PostgreSQL

Материализованное представление в PostgreSQL — объект базы данных, хранящий результат запроса SELECT физически на диске, в отличие от обычного представления, которое повторно выполняет свой запрос при каждом обращении. Материализованные представления создаются командой CREATE MATERIALIZED VIEW summary AS SELECT region, SUM(revenue) FROM sales GROUP BY region и обновляются по требованию командой REFRESH MATERIALIZED VIEW [CONCURRENTLY] summary, что делает их идеальными для дорогостоящих запросов с агрегацией и JOIN в реляционной базе данных, где незначительное устаревание данных допустимо в обмен на значительно более быстрое чтение. Параметр CONCURRENTLY для REFRESH позволяет читать из старых данных, пока строится новый снимок, но требует наличия уникального индекса на материализованном представлении — важное соображение при оптимизации запросов для высокодоступных развёртываний PostgreSQL. Индексы можно создавать на столбцах материализованного представления так же, как на обычных таблицах (CREATE INDEX ON summary (region)), а сочетание индексированных материализованных представлений с запланированными заданиями REFRESH является стандартным паттерном PostgreSQL для ускорения дашбордов и отчётных запросов, которые иначе перегружали бы живую OLTP-базу данных.

Как это работает

MATERIALIZED VIEW соединяет данные между таблицами: INNER, LEFT/RIGHT/FULL OUTER, CROSS, LATERAL (per-row подзапрос), SELF (alias той же таблицы). View — сохранённые запросы (CREATE VIEW v AS SELECT ...); материализованные view (CREATE MATERIALIZED VIEW ...) кешируют результат на диск, требуют REFRESH. Оконные функции (OVER (PARTITION BY ... ORDER BY ...)) считают per-row агрегацию без коллапса строк. CTE (WITH ... AS) именуют подзапросы для читаемости.

Когда применять

View — для энкапсуляции сложных запросов, переиспользуемых вызывающими: версионированная API-поверхность над схемой. Материализованные view — когда подлежащий запрос дорогой, staleness секунд-часов допустим. LATERAL — когда подзапросу нужны колонки внешнего (top-N per group — канонический пример). Оконные функции вместо сложных self-join — для running totals, рангов, перцентилей.

Типичные ошибки

Ловушки MATERIALIZED VIEW: глубоко вложенные view (SELECT из view, join-ящего три view — планировщик видит один большой запрос, может выбрать плохой план); никогда не рефрешат materialized view (stale данные неделями); FULL OUTER JOIN, где надо INNER (NULL-потоп); cartesian-взрыв от пропущенного JOIN-условия (5 таблиц × 5 unrelated строк = миллионы). Всегда EXPLAIN для join перед деплоем.

Связанные понятия

Полезные ресурсы