Недавно я работал над добавлением в материализованные представления StarRocks поддержки нескольких выражений , поэтому подробно разобрал весь путь — от создания MV до его обновления (refresh).
Создание материализованного представления
Пример:
CREATE
MATERIALIZED VIEW mv_test99
REFRESH ASYNC EVERY(INTERVAL 60 MINUTE)
PARTITION BY p_time
PROPERTIES (
"partition_refresh_number" = "1"
)
AS
select date_trunc("day", a.datekey) as p_time, sum(a.v1) as value
from par_tbl1 a
group by p_time, a.item_id;
На этапе парсинга и анализа вызывается:com.starrocks.sql.analyzer.MaterializedViewAnalyzer.MaterializedViewAnalyzerVisitor#visitCreateMaterializedViewStatemen

Эта процедура преобразует оператор создания в объект CreateMaterializedViewStatement (используется ANTLR) и выполняет семантический анализ и базовые проверки, в том числе:
корректность выражения партиционирования;
корректность ссылок на базовые таблицы и базы данных;
согласованность схемы выходных столбцов и свойств MV.

Далее управление переходит в:com.starrocks.server.LocalMetastore#createMaterializedView()
Ключевые задачи этого этапа:
Проверка существования целевой базы данных и одноименного MV.
-
Инициализация базовой информации MV:
построение схемы столбцов (schema);
валидация схемы;
инициализация свойств, включая партиционирование.
-
Настройка стратегии обновления:
выбор режима (ASYNC, SYNC, MANUAL, INCREMENTAL);
для асинхронного режима — установка интервала, времени начала и валидация параметров.
-
Создание объекта MV:
выбор типа в зависимости от режима развертывания (разделение хранения и вычислений или интегрированный режим);
настройка индексов, сортировочных ключей, комментариев, привязка базовых таблиц.
-
Партиционирование:
для непартиционированного MV — создание единственной партиции и ее свойств;
для партиционированного MV — разбор выражения партиционирования и построение соответствия партиций.
-
Привязка тома хранения:
для cloud‑native MV — привязка storage volume.

Сериализация ключевых данных
Часть сведений должна переживать перезапуск FE, чтобы при повторной загрузке быть доступной механизмам refresh и анализа. Поэтому ключевые поля сериализуются в метаданные, которые периодически сохраняются в директории fe/meta.

Типичные выносимые в метаданные артефакты:
исходный SQL создания MV;
выражения партиционирования и их сопоставления;
сервисные свойства, влияющие на refresh.
Поля помечаются аннотацией @SerializedName, например:
@SerializedName(value = "partitionExprMaps")
private Map<ExpressionSerializedObject, ExpressionSerializedObject> serializedPartitionExprMaps;
Собственно преобразование выполняется в:
com.starrocks.catalog.MaterializedView#gsonPreProcesscom.starrocks.catalog.MaterializedView#gsonPostProcess
Синхронизация и загрузка метаданных
В кластере FE лидер периодически создает снимки метаданных:
поток
checkpoint(checkpoint) решает, когда нужно формировать новыйimage.${JournalId}(image) — обычно при достижении порога по количеству событий в журнале изменений (edit log), по умолчанию 50 000;

метаданные пишутся и читаются согласованно всеми FE (leader/follower).

Упрощенно процесс выглядит так:
Проверка необходимости формирования нового image.
Загрузка метаданных из текущего image в память.
Чтение последних журналов (
Journal) изbdbи ихreplayповерх загруженного состояния.Генерация нового image из актуального состояния в памяти.
Очистка старых image.
-
Уведомление follower‑узлов FE о новом image с последующей синхронизацией.

Обновление MV (refresh)

Сразу после успешного создания MV инициируется первичное обновление. Далее обновления могут запускаться по расписанию (ASYNC EVERY ...), вручную или по событиям в базовых таблицах (подробнее).
Синхронизация партиций
Ключевой шаг каждого refresh — выравнивание партиций MV с партициями базовых таблиц. Для range‑партиционирования основная логика сосредоточена в:
com.starrocks.scheduler.mv.MVPCTRefreshRangePartitioner#syncAddOrDropPartitions
Что делает процедура:
Вычисляет разницу партиций между MV и базовыми таблицами в заданном диапазоне.
-
Синхронизирует партиции:
удаляет устаревшие партиции MV, которые больше не сопоставляются базовым таблицам;
добавляет недостающие партиции.

После синхронизации рассчитывается подмножество партиций, подлежащих обновлению в этой итерации. По умолчанию MV обновляет ограниченное число партиций за запуск; параметр:
"partition_refresh_number"— задает размер партии. Оставшиеся партиции будут поставлены на последующие запуски, формируя «хвост» заданий до полного охвата диапазона.
Поддержка нескольких выражений в UNION и VirtualPartitions (PR #60035)
Практическая проблема, решенная в [1]: если в определении MV используется UNION ALL с выражениями сдвига дат (date_add/date_sub), обычного сопоставления партиций может быть недостаточно. Например:
CREATE MATERIALIZED VIEW mv_test99
REFRESH ASYNC EVERY(INTERVAL 60 MINUTE)
PARTITION BY p_time
PROPERTIES ("partition_refresh_number" = "1")
AS
select date_trunc('day', a.datekey) as p_time, sum(a.v1) as value
from par_tbl1 a
group by p_time, a.item_id
union all
select date_trunc('day', date_add(b.datekey, INTERVAL 1 DAY)) as p_time, sum(b.v1) as value
from par_tbl1 b
group by p_time, item_id;
Без дополнительной логики одна из партиций может не обновиться, так как новая «производная» дата выходит за рамки партиций, вычисленных напрямую из базовой таблицы. В реальном кейсе отсутствовала партиция p20250103_20250104.
Решение в [1]:
При создании MV, если встречается
UnionRelation, сохраняются выражения выходных столбцовUNIONдля последующего вычисления «виртуальных партиций» (VirtualPartitions).При refresh ранее сохраненные VirtualPartitions добавляются к набору партиций, подлежащих обновлению в текущем проходе.
-
VirtualPartitions — это партиции, «выведенные» из партиций базовой таблицы с применением выражений времени (
date_add/date_sub). Они:используются только в контексте refresh MV;
не меняют схему MV и не влияют на базовую таблицу;
позволяют «догружать» смежные диапазоны, которые появляются из‑за сдвигов дат в
UNION ALL.
Таким образом, MV корректно обновляется даже при наличии нескольких выражений в UNION ALL, и «выпадающие» партиции больше не теряются.
Примечание по другим сценариям:
Для
inner joinрезультат — пересечение, добавлениеdate_addна правой стороне обычно не влияет на множество целевых партиций.Для
left joinрезультат определяется левой таблицей; добавочные даты справа не расширяют область обновления, поэтому VirtualPartitions обычно не требуются.Концепция VirtualPartitions главным образом востребована для
UNION ALLс временными сдвигами; для большинства join‑сценариев стандартной логики достаточно.
Итоги
Создание MV проходит через анализ (ANTLR →
CreateMaterializedViewStatement), валидацию, инициализацию свойств, настройку refresh и партиционирования.Ключевые метаданные сериализуются и сохраняются в
fe/meta; лидер FE периодически формируетimageчерезcheckpoint, а изменения фиксируются вedit log.Refresh состоит из синхронизации партиций и порционного обновления выбранных диапазонов (
partition_refresh_number).PR [1] добавляет поддержку нескольких выражений в
UNION ALLза счет механизма VirtualPartitions, гарантируя, что смещенные датой диапазоны не будут пропущены при обновлении.
PhoenixLi Автор
[1] Поддержка нескольких выражений: https://github.com/StarRocks/starrocks/pull/60035