Материализованные представления и проекции
Один из частых вопросов пользователей — когда следует использовать материализованные представления, а когда проекции. В этой статье мы рассмотрим ключевые различия между ними и разберёмся, почему в определённых сценариях стоит предпочесть один подход другому.
Сводка ключевых различий
В таблице ниже приведены ключевые различия между материализованными представлениями и проекциями по различным аспектам.
| Аспект | Материализованные представления | Проекции |
|---|---|---|
| Data storage and location | Сохраняют свои результаты в отдельной, явно заданной целевой таблице, выступая в роли триггеров вставки при INSERT в исходную таблицу. | Проекции создают оптимизированные структуры данных, которые физически хранятся рядом с основными данными таблицы и невидимы для пользователя. |
| Update mechanism | Работают синхронно при INSERT в исходную таблицу (для инкрементальных материализованных представлений). Примечание: их также можно планировать по расписанию с помощью обновляемых материализованных представлений. | Асинхронные обновления в фоновом режиме при INSERT в основную таблицу. |
| Query interaction | Работа с материализованными представлениями требует прямого выполнения запросов к целевой таблице, то есть пользователи должны знать о существовании материализованных представлений при написании запросов. | Проекции автоматически выбираются оптимизатором запросов ClickHouse и являются прозрачными в том смысле, что пользователю не нужно изменять свои запросы к таблице с проекцией, чтобы её использовать. Начиная с версии 25.6 также можно фильтровать более чем по одной проекции. |
Handling UPDATE / DELETE | Не реагируют автоматически на операции UPDATE или DELETE над исходной таблицей, так как материализованные представления не обладают информацией об исходной таблице и работают только как триггеры вставки в исходную таблицу. Это может приводить к потенциальной несвежести данных между исходной и целевой таблицами и требует обходных решений или периодического полного обновления (через обновляемое материализованное представление). | По умолчанию несовместимы с удалёнными (DELETED) строками (особенно с облегчёнными удалениями — lightweight deletes). Параметр lightweight_mutation_projection_mode (v24.7+) может включить совместимость. |
JOIN support | Да. Обновляемые материализованные представления могут использоваться для сложной денормализации. Инкрементальные материализованные представления срабатывают только при вставках в самую левую таблицу. | Нет. Операции JOIN не поддерживаются в определениях проекций для фильтрации материализованных данных. Однако запросы, которые делают JOIN таблиц с проекциями, работают нормально — проекции оптимизируют доступ к отдельным таблицам. |
WHERE clause in definition | Да. Условия WHERE могут быть включены для фильтрации данных до материализации. | Нет. Условия WHERE не поддерживаются в определениях проекций для фильтрации материализованных данных. |
| Chaining capabilities | Да, целевая таблица одного материализованного представления может быть источником для другого материализованного представления, что позволяет строить многоступенчатые конвейеры. | Нет. Проекции нельзя связывать в цепочку. |
| Applicable table engines | Могут использоваться с различными движками исходных таблиц, но целевые таблицы обычно принадлежат семейству MergeTree. | Доступны только для движков таблиц семейства MergeTree. |
| Failure handling | Сбой во время вставки данных означает потерю данных в целевой таблице, что может привести к несогласованности данных. | Сбои тихо обрабатываются в фоновом режиме. Запросы могут бесшовно комбинировать материализованные и нематериализованные части данных. |
| Operational overhead | Требуют явного создания целевой таблицы и часто ручного дозаполнения (backfill). Управление согласованностью данных при UPDATE/DELETE повышает сложность. | Проекции автоматически поддерживаются и синхронизируются и, как правило, создают меньшую операционную нагрузку. |
FINAL query compatibility | В целом совместимы, но часто требуют GROUP BY по целевой таблице. | Не работают с запросами FINAL. |
| Lazy materialization | Да. | Следите за проблемами совместимости проекций при использовании механизмов ленивой материализации. Возможно, потребуется установить query_plan_optimize_lazy_materialization = false. |
| Parallel replicas | Да. | Нет. |
optimize_read_in_order | Да. | Да. |
| Lightweight updates and deletes | Да. | Нет. |
Сравнение материализованных представлений и проекций
Когда стоит выбирать материализованные представления
Использование материализованных представлений стоит рассмотреть, когда:
- Вы работаете с ETL в режиме реального времени и многостадийными конвейерами обработки данных: Нужно выполнять сложные преобразования, агрегации или маршрутизацию данных по мере их поступления, возможно, через несколько стадий, связывая представления в цепочки.
- Вам требуется сложная денормализация: Нужно заранее объединить данные из нескольких источников (таблиц, подзапросов или словарей) в одну таблицу, оптимизированную для запросов, особенно если допустимы периодические полные обновления с использованием обновляемых материализованных представлений.
- Вам нужен явный контроль над схемой: Требуется отдельная целевая таблица с собственной схемой и движком для предварительно вычисленных результатов, что обеспечивает большую гибкость при моделировании данных.
- Вы хотите фильтровать на этапе ингестии: Нужно отфильтровать данные до того, как они будут материализованы, уменьшая объём данных, записываемых в целевую таблицу.
Когда следует избегать материализованных представлений
Следует рассмотреть отказ от использования материализованных представлений, когда:
- Исходные данные часто обновляются или удаляются: Без дополнительных стратегий поддержания согласованности между исходными и целевыми таблицами инкрементальные материализованные представления могут устаревать и становиться несогласованными.
- Предпочитаются простота и автоматическая оптимизация: Если вы не хотите управлять отдельными целевыми таблицами.
Когда следует использовать проекции
Рекомендуется рассматривать использование проекций, когда:
- Оптимизируете запросы для одной таблицы: ваша основная цель — ускорить запросы к одной базовой таблице за счёт задания альтернативных порядков сортировки, оптимизации фильтров по столбцам, которые не входят в первичный ключ, или предварительного вычисления агрегаций для одной таблицы.
- Вам нужна прозрачность запросов: вы хотите, чтобы запросы по-прежнему выполнялись к исходной таблице без изменений, полагаясь на ClickHouse при выборе наилучшего расположения данных для конкретного запроса.
Когда следует избегать проекций
Рекомендуется избегать использования проекций в следующих случаях:
- Требуется сложная трансформация данных или многоэтапный ETL: Определения проекций не поддерживают операции
JOIN, не могут быть объединены в цепочки для построения многошаговых конвейеров и не работают с некоторыми возможностями SQL, такими как оконные функции или сложные выраженияCASE. Хотя запросы к таблицам с проекциями могут свободно использоватьJOIN, сами проекции не подходят для сложной трансформации данных. - Нужна явная фильтрация материализованных данных: Проекции не поддерживают использование предложения
WHEREв определении для фильтрации данных, которые материализуются в саму проекцию. - Используются табличные движки, отличные от MergeTree: Проекции доступны исключительно для таблиц, использующих семейство движков
MergeTree. - Запросы с
FINALявляются критически важными: проекции не работают с запросамиFINAL, которые иногда используются для дедупликации. - Вам нужны параллельные реплики, так как они не поддерживаются при использовании проекций.
Резюме
Материализованные представления и проекции — это мощные инструменты в вашем арсенале для оптимизации запросов и преобразования данных, и в целом мы не рекомендуем рассматривать их использование как взаимоисключающий выбор. Вместо этого их можно применять взаимодополняющим образом, чтобы получить максимальную отдачу от запросов. Таким образом, выбор между материализованными представлениями и проекциями в ClickHouse на самом деле зависит от конкретного сценария использования и паттернов доступа.
В качестве общего практического правила стоит рассматривать использование материализованных представлений, когда вам нужно агрегировать данные из одной или нескольких исходных таблиц в целевую таблицу или выполнять сложные преобразования в больших масштабах. Материализованные представления отлично подходят для переноса работы по выполнению ресурсоёмких агрегирующих вычислений с момента выполнения запроса на момент вставки данных. Это отличный выбор для ежедневных или ежемесячных сводок, дашбордов в реальном времени или агрегированных обзоров данных.
С другой стороны, имеет смысл использовать проекции, когда необходимо оптимизировать запросы, которые фильтруют по другим столбцам, чем те, что используются в первичном ключе таблицы, определяющем физический порядок данных на диске. Они особенно полезны, когда изменить первичный ключ таблицы больше невозможно или когда ваши паттерны доступа более разнообразны, чем то, что может обеспечить первичный ключ.