Материализованные представления
Materialized view (MV) обладают свойствами как постоянной table, так и view.
Оно определяется аналогично представлению, и его исходный запрос используется движком для
заполнения нижележащей MV table строками данных. Не допускается изменять
данные материализованного представления с помощью DML-операторов. Единственный способ обновить содержимое MV —
выполнить специальный новый оператор REFRESH (см. ниже). Как и обычная таблица,
MV может иметь индексы любого вида. В отличие от таблиц, для MV не допускается создавать
ограничения и триггеры.
Синтаксис
Создание, изменение и удаление
CREATE [OR ALTER] MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
ALTER MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
Создаёт новое или изменяет существующее MV с использованием указанного запроса и необязательного списка
имён столбцов. Необязательное предложение WITH DATA указывает, что MV должно быть заполнено
данными сразу после создания (изменения). Если указано WITH NO DATA или
это предложение опущено, MV не заполняется данными и остаётся пустым.
ALTER также удаляет все существующие индексы MV. Если существует обычное (т.е. не материализованное)
представление с тем же именем, возникает ошибка.
RECREATE MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
[WITH [NO] DATA]
Удаляет материализованное или обычное представление, если оно существует, и создаёт новое материализованное представление.
Отдельной команды для удаления MV нет, используйте обычный оператор DROP VIEW.
Специальные команды
ALTER MATERIALIZED VIEW <view_name> [(columns_names)]
AS <query>
TO NOT MATERIALIZED
Особый вид оператора ALTER, который преобразует материализованное представление в обычное представление с тем же именем. Зависимые объекты не затрагиваются. Все существующие индексы и строки данных бывшего MV удаляются.
ALTER VIEW <view_name> [(columns_names)]
AS <query>
TO MATERIALIZED
Особый вид оператора ALTER, который преобразует обычное представление в материализованное представление с тем же именем. Зависимые объекты не затрагиваются.
Обновление данных материализованных представлений
REFRESH MATERIALIZED VIEW [CONCURRENTLY|DROP DATA] [CASCADE]
Выполняет запрос MV и заменяет данные MV результатом запроса. Все индексы MV соответствующим образом обновляются. Это DDL-команда, и фактическое выполнение откладывается до COMMIT текущей транзакции. Существует несколько форм этой команды:
1. Полная перезагрузка в монопольном режиме:
REFRESH MATERIALIZED VIEW <view_name>
деактивирует все активные индексы, удаляет все существующие данные, заполняет таблицу MV
строками из запроса MV и активирует все индексы, которые были деактивированы ранее.
Это самый быстрый способ обновления, если в таблицах, составляющих запрос MV, было много изменений.
Для обеспечения того, чтобы никакое другое соединение не пыталось обратиться к MV во время его обновления,
требуется монопольная резервация таблицы MV.
Этот подход также используется операторами CREATE [OR ALTER], ALTER и RECREATE
для начальной загрузки данных.
Примечание: если на этапе загрузки данных происходит какая-либо ошибка, то все только что загруженные данные будут
удалены, ранее деактивированные индексы будут активированы (как пустые), а исходная
ошибка будет сообщена пользователю. То есть таблица MV будет очищена, и это нельзя
отменить даже откатом. Ожидается, что причина ошибки будет исправлена пользователем
(например, путём исправления запроса MV), и оператор REFRESH будет повторён снова.
Примечание: если при активации некоторых индексов (после этапа загрузки данных)
происходят ошибка(и), то этот индекс(ы) останется в неактивном состоянии. Такие ошибки не повлияют
на уже загруженные данные и на другие индексы. Фиксация транзакции завершится успешно, а ошибки построения индексов
будут помещены в status-vector как предупреждения. Такие индексы можно
активировать позже с помощью обычных операторов ALTER INDEX <index_name> ACTIVE, если
это необходимо.
2. Обновление только изменённых строк в разделяемом режиме:
REFRESH MATERIALIZED VIEW <view_name> CONCURRENTLY
Эта вторая форма не требует монопольной резервации и позволяет параллельным соединениям выполнять операторы, ссылающиеся на MV, во время его обновления. В этом случае движок создаёт два упорядоченных курсора для данных таблицы MV и для результирующего набора запроса MV. Затем используется алгоритм слияния для обновления изменённых строк, вставки новых строк и удаления строк, которые больше не существуют. Все изменения строк MV выполняются под управлением транзакции, поэтому обеспечивается безопасный и согласованный параллельный доступ к таблице MV. Оба курсора упорядочиваются на основе списка столбцов уникального индекса.
Для работы этого алгоритма на MV должен быть построен уникальный индекс.
Кроме того, текст запроса представления, хранящийся в столбце RDB$VIEW_SOURCE, не должен обнуляться,
поскольку он используется движком для создания внутреннего оператора слияния.
Эту форму оператора REFRESH следует предпочитать первой, когда требуется параллельный
доступ или когда в таблицах запроса MV с момента предыдущего обновления было не так много изменений.
Примечание: если запрос MV содержит предложение ORDER BY, естественный порядок строк может
измениться после параллельного обновления и больше не удовлетворять предложению ORDER BY.
3. Удаление всех данных (монопольный режим):
REFRESH MATERIALIZED VIEW <view_name> DROP DATA
Этот оператор удаляет данные из таблицы MV и индексов. Он полезен, когда администратору БД нужно
освободить пространство, занимаемое данными и индексами MV. Требуется блокировка EX, как и в первой
форме оператора REFRESH.
4. Каскадное обновление
Используйте необязательное предложение CASCADE, чтобы обновить все материализованные представления, от которых
зависит данное MV. Порядок обновления гарантирует, что каждое MV обрабатывается один раз и только
после всех MV, от которых оно зависит.
- Использование
CONCURRENTLYсCASCADEтребует, чтобы все обновляемые MV имели уникальный индекс, иначе возникнет ошибка. - Использование
DROP DATAсCASCADEудалит данные всех затронутых MV. - Оператор помещает предупреждение с именем каждого MV, который будет обработан, в status-vector. Это позволяет заранее (до фиксации) узнать список и порядок затронутых MV.
Поддержка gbak
gbak backup не требует специальной поддержки. Данные материализованного представления не попадают в файл резервной копии — так же, как и для обычных представлений.
gbak restore обновляет все материализованные представления в самом конце процесса восстановления. MV обновляются в правильном порядке с учётом их зависимостей друг от друга (см. каскадное обновление).
Есть новый параметр командной строки, позволяющий gbak не обновлять MV: -NO_MATVIEWS.
Его можно сократить до 4 начальных букв: -NO_M.
Соответствующая опция в Services API для действия isc_action_svc_restore —
isc_spb_res_no_matviews.
Примечание: резервная копия с материализованным(и) представлением(ями) не может быть восстановлена в версии Firebird,
которая не поддерживает MV. Чтобы перейти на такую версию Firebird, используйте оператор ALTER MATERIALIZED
VIEW ... TO NOT MATERIALIZED перед созданием резервной копии. Это может быть улучшено в дальнейшем.
Видео и презентация
Вебинар по материализованным представлениям в Firebird / HQbird:
Презентация (PDF): Materialized Views in Firebird