Производительность БД

Материализованные представления: как ускорить тяжёлые отчёты в базе данных

Материализованное представление — это результат SQL-запроса, который база данных сохраняет на диске как отдельную таблицу, а не пересчитывает при каждом обращении. Обычное представление (VIEW) — это просто сохранённый текст запроса: каждый раз, когда к нему обращаются, база честно выполняет его заново. Материализованное представление выполняется один раз, а дальше отдаёт готовые данные, пока их не обновят вручную или по расписанию.

В чём разница между обычным VIEW и материализованным?

Обычное представление — это, по сути, ярлык для сложного запроса. Оно ничего не хранит, а просто подставляет свой текст в тот запрос, который его вызвал. Если под представлением лежат несколько JOIN'ов, агрегаций и подзапросов по миллионам строк, каждое обращение к нему будет таким же медленным, как и исходный запрос.

Материализованное представление устроено иначе: оно один раз выполняет тяжёлый запрос и сохраняет результат физически, как обычную таблицу. Дальше чтение из него — это просто чтение готовых строк, быстрое и предсказуемое, независимо от того, насколько сложным был исходный запрос.

Когда обычной оптимизации запросов и индексов уже мало?

Индексы отлично ускоряют выборку конкретных строк, но плохо помогают, когда запрос агрегирует данные по всей таблице: считает суммы, средние значения, группирует по десяткам параметров. Такие запросы физически вынуждены пройти по огромному объёму данных, и никакой индекс это не отменит полностью.

Именно здесь на сцену выходят материализованные представления. Типичный кандидат — тяжёлый отчёт для дашборда: «продажи по регионам за последний квартал», «топ товаров по категориям», «активность пользователей по дням». Если такой отчёт запрашивают десятки раз в день, а данные для него меняются не поминутно, гораздо разумнее посчитать его один раз и отдавать готовый результат.

Как обновляются данные в материализованном представлении?

Тут есть важный нюанс: данные в материализованном представлении не обновляются автоматически при каждом изменении исходных таблиц. Обновление — отдельная операция, которую нужно запускать вручную или по расписанию. В разных СУБД это делается по-разному: где-то есть команда полного пересчёта, где-то поддерживается более щадящий инкрементальный вариант, обновляющий только изменившиеся строки.

Из-за этого материализованные представления всегда содержат чуть устаревшие данные — с момента последнего обновления. Для отчётов и аналитики это обычно некритично: никто не ждёт от квартального дашборда данных с точностью до секунды. А вот для операций, где важна абсолютная актуальность — остатки на складе перед оформлением заказа, баланс счёта — такой подход не годится.

Клауд АйСи — цифровые сервисы для бизнеса в одном кабинете: 1С в облаке с ежедневными резервными копиями, конструктор сайтов, Умный онлайн-чат и проверка контрагентов.
Ваши данные под защитой. Есть бесплатные тарифы навсегда.

Какие СУБД поддерживают эту технологию?

Материализованные представления — далеко не новая идея: концепция появилась ещё в промышленных СУБД в конце девяностых и с тех пор прочно вошла в арсенал баз данных для аналитики. Сегодня PostgreSQL поддерживает их «из коробки» как встроенный объект базы. В MySQL нативной поддержки нет, поэтому там роль материализованных представлений обычно играют обычные таблицы, которые периодически перезаполняются через задачи по расписанию, — по сути та же идея, только собранная вручную.

Что важно учесть, прежде чем использовать материализацию?

Главный компромисс простой: вы меняете скорость чтения на актуальность данных и дополнительное место на диске. Материализованное представление занимает столько же места, сколько заняла бы обычная таблица с теми же данными, а на каждое обновление тратятся ресурсы сервера — иногда сопоставимые с исходным тяжёлым запросом.

Есть и практические грабли:

  • Забытое расписание обновления — и отчёт молча показывает данные недельной давности, а никто этого не замечает.
  • Слишком частое обновление больших представлений может само по себе создавать нагрузку, сравнимую с той, от которой хотели уйти.
  • Материализованное представление нужно ре-индексировать так же, как обычную таблицу, — иначе выигрыш в скорости теряется.

Как понять, что именно стоит материализовать?

Хороший кандидат для материализации отвечает трём условиям одновременно: запрос действительно тяжёлый (агрегации, множественные JOIN, большие объёмы данных), его выполняют часто, а исходные данные меняются заметно реже, чем к результату обращаются. Классический пример — витрины данных для BI-систем и внутренние дашборды руководства: там данные обновляют раз в час или раз в день, а смотрят в них десятки раз за это время.

Если же запрос выполняется редко или данные под ним меняются практически с той же частотой, что и обращения к отчёту, — материализация не даст выигрыша, а только добавит сложности в обслуживание базы.

Что делать, если своими руками разбираться с этим некогда?

Настройка материализованных представлений, расписаний обновления и мониторинга их «свежести» — задача, требующая понимания и базы данных, и бизнес-логики отчётов. Для компаний, которым важен результат, а не возня с администрированием, платформа «Клауд АйСи» предлагает управляемые базы данных, где значительная часть рутины по настройке, резервному копированию и оптимизации производительности берёт на себя команда сервиса, — можно сосредоточиться на самих запросах и отчётах, а не на инфраструктуре под ними.

1С в облаке с резервным копированием

Зарегистрируйтесь и подключите облачную 1С — ежедневные бэкапы и обновления уже включены.

Частые вопросы

Материализованное представление — это то же самое, что кэш запроса?

Идея похожа, но кэш запроса обычно живёт в оперативной памяти на уровне приложения или СУБД и сбрасывается автоматически при изменении данных. Материализованное представление — это физический объект в базе данных, который обновляется только явной командой или по расписанию.

Можно ли строить индексы на материализованном представлении?

Да, и это стоит делать: поскольку материализованное представление физически хранится как таблица, обычные индексы на нём работают точно так же и ещё сильнее ускоряют выборки из него.

Что произойдёт, если не обновлять материализованное представление вовремя?

Данные в нём просто останутся такими, какими были на момент последнего обновления. Ошибки не будет — но отчёт или дашборд начнёт показывать устаревшую информацию, что легко заметить не сразу.

Подходит ли материализация для данных, которые меняются каждую секунду?

Нет, для по-настоящему живых данных это плохой выбор: обновлять представление придётся слишком часто, и выигрыш в производительности будет съеден затратами на пересчёт.