Learning Platform
Глоссарий Troubleshooting
Урок 05.05 · 20 мин
Средний
Refreshable MVREFRESH EVERYREFRESH AFTERDEPENDS ONAPPENDsystem.view_refreshes

Refreshable MV: периодическое обновление

Инкрементальные MV (уроки 1-3) срабатывают на каждый INSERT — это реактивная модель. Refreshable MV — это принципиально другой механизм: периодический полный пересчёт по расписанию. Refreshable MV не имеет триггера на INSERT — это периодический полный пересчёт, а не инкрементальное обновление.


Статус: GA с 24.10

Refreshable MV стали production-ready начиная с ClickHouse 24.10. Никаких экспериментальных флагов не требуется. В версии 26.3 LTS это стабильная, полностью поддерживаемая функциональность.


REFRESH EVERY: фиксированный интервал

REFRESH EVERY запускает полный пересчёт через фиксированные интервалы времени:

CREATE MATERIALIZED VIEW hourly_report
REFRESH EVERY 1 HOUR
TO hourly_report_target AS
SELECT
    toStartOfHour(event_time) AS hour,
    count() AS total_events,
    uniq(user_id) AS unique_users
FROM raw_events
GROUP BY hour;

ClickHouse полностью заменяет содержимое target-таблицы при каждом обновлении. Старые данные удаляются, новые вставляются. Это поведение по умолчанию (REPLACE).

Интервал отсчитывается от полуночи UTC: REFRESH EVERY 1 HOUR означает обновление в 00:00, 01:00, 02:00 и так далее.


REFRESH AFTER: относительный интервал

REFRESH AFTER запускает следующий пересчёт через заданное время после завершения предыдущего:

CREATE MATERIALIZED VIEW analytics_report
REFRESH AFTER 30 MINUTE
TO analytics_report_target AS
SELECT
    toDate(event_time) AS date,
    sum(revenue) AS daily_revenue
FROM orders
GROUP BY date;

Разница с REFRESH EVERY: если пересчёт занимает 10 минут и установлен REFRESH AFTER 30 MINUTE, следующий запуск будет через 30 минут после завершения, а не через 30 минут от начала. Это предотвращает наложение длительных пересчётов.


DEPENDS ON: каскадное обновление

Когда один refreshable MV зависит от результата другого, используйте DEPENDS ON для гарантии порядка:

-- Первый уровень: ежечасная агрегация
CREATE MATERIALIZED VIEW daily_stats
REFRESH EVERY 1 HOUR
TO daily_stats_target AS
SELECT
    toDate(event_time) AS date,
    event_type,
    count() AS cnt
FROM raw_events
GROUP BY date, event_type;

-- Второй уровень: месячный отчёт, зависит от daily_stats
CREATE MATERIALIZED VIEW monthly_report
REFRESH EVERY 1 HOUR
DEPENDS ON daily_stats
TO monthly_report_target AS
SELECT
    toStartOfMonth(date) AS month,
    sum(cnt) AS total_events
FROM daily_stats_target
GROUP BY month;

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


APPEND режим

По умолчанию каждый refresh полностью заменяет данные в target-таблице. Режим APPEND добавляет новые строки без удаления существующих:

CREATE MATERIALIZED VIEW event_snapshots
REFRESH EVERY 1 HOUR
APPEND
TO event_snapshots_target AS
SELECT
    now() AS snapshot_time,
    count() AS current_events,
    uniq(user_id) AS current_users
FROM raw_events
WHERE event_time >= now() - INTERVAL 1 HOUR;

APPEND полезен для построения временных рядов снимков: каждый час добавляется новая строка с текущими метриками. Target-таблица растёт со временем.


Отличие от инкрементальных MV

WARNING

Refreshable MV и инкрементальные MV — это два разных механизма с одинаковым названием “материализованное представление”. Не путайте их.

ХарактеристикаИнкрементальная MVRefreshable MV
ТриггерINSERT в source-таблицуРасписание (REFRESH EVERY / AFTER)
ОбработкаТолько новые строки из INSERT-блокаПолный пересчёт всего SELECT
SQL ограниченияНет JOINs, table functions, UNIONПолная свобода SQL
BackfillingРучной INSERT INTO … SELECTАвтоматический при каждом refresh
LatencyРеальное время (миллисекунды)По расписанию (минуты-часы)

Инкрементальная MV обрабатывает только новые строки из каждого INSERT-блока и не видит состояние таблицы. Refreshable MV выполняет полный SELECT по всем данным при каждом обновлении — это даёт полную свободу SQL (JOINs, UNION, table functions, url()), но за счёт latency.


Полная свобода SQL

В отличие от инкрементальных MV, refreshable MV не имеет ограничений на SELECT:

-- JOIN между таблицами
CREATE MATERIALIZED VIEW enriched_events
REFRESH EVERY 2 HOUR
TO enriched_events_target AS
SELECT
    e.event_time,
    e.user_id,
    u.country,
    e.event_type
FROM raw_events e
JOIN users u ON e.user_id = u.id;

-- Table function url() для внешних данных
CREATE MATERIALIZED VIEW exchange_rates
REFRESH EVERY 1 DAY
TO exchange_rates_target AS
SELECT *
FROM url('https://api.example.com/rates.csv', CSVWithNames);

Это возможно потому, что refreshable MV выполняет полный SELECT, а не обрабатывает отдельные INSERT-блоки.


Мониторинг: system.view_refreshes

Состояние всех refreshable MV доступно в системной таблице:

SELECT
    database,
    view,
    status,
    last_refresh_result,
    last_refresh_time,
    next_refresh_time,
    retry_count
FROM system.view_refreshes
FORMAT Vertical;

Возможные значения status: Scheduled, Running, WaitingForDependencies. last_refresh_result покажет ошибку, если предыдущий пересчёт завершился неудачно.


Когда использовать refreshable MV

TIP

Используйте refreshable MV, когда допустима задержка (минуты-часы) и нужна полная свобода SQL: JOINs, UNION, агрегация по всей таблице, внешние источники данных. Для real-time агрегации используйте инкрементальные MV.

Типичные сценарии:

  • Периодические отчёты: ежечасные/ежедневные дашборды
  • ETL-конвейеры: каскадная трансформация данных через DEPENDS ON
  • Обогащение данных: JOIN с dimension-таблицами
  • Внешние источники: импорт через url(), s3(), и другие table functions

Ключевые выводы

  1. Refreshable MV — это периодический полный пересчёт, не реактивный триггер на INSERT.
  2. REFRESH EVERY — фиксированный интервал от полуночи UTC. REFRESH AFTER — относительный интервал от завершения предыдущего пересчёта.
  3. DEPENDS ON гарантирует порядок каскадного обновления: зависимая MV ждёт завершения source-MV.
  4. APPEND добавляет строки без удаления. По умолчанию — полная замена (REPLACE).
  5. system.view_refreshes — единая точка мониторинга состояния всех refreshable MV.
MATERIALIZED VIEW в PostgreSQL: REFRESH и использование Batch-обработка: планирование, окна, инкрементальность

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Refreshable MV monthly_report зависит от daily_stats (DEPENDS ON daily_stats). daily_stats обновляется каждый час. Инженер хочет, чтобы monthly_report обновлялся только после завершения daily_stats. Какой DDL корректен?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7