Подход на основе только представлений для максимальной актуальности данных
На этой странице в примерах кода используется Snowflake, но подход на основе только представлений можно адаптировать и для других хранилищ данных.
Для некоторых рабочих нагрузок самый простой подход, наиболее близкий к работе «в реальном времени», — материализовать всё в виде представлений над непрерывно обновляемой исходной таблицей. Если преобразования очень легковесны, а источник уже обновляется почти в реальном времени, такой подход позволяет практически не увеличивать задержку источника.
Когда использовать подход на основе только представлений
Используйте этот подход, если:
- Актуальность источника уже «достаточно хорошая» (например, сервис загрузки данных или операционная система записывает данные в таблицу хранилища каждые несколько секунд или минут).
- Преобразования очень легковесны, например:
- Простой выбор или переименование столбцов
- Одно-два соединения с небольшой справочной таблицей
- Минимальное использование ресурсоёмких агрегаций или оконных функций либо их полное отсутствие
- Для вас важнее всего сохранить задержку исходной таблицы, и вы готовы пожертвовать некоторой производительностью запросов при чтении.
- Лучше всего этот подход подходит для небольших и средних таблиц с простыми запросами.
Типичные примеры:
- Дашборды с текущим состоянием системы (например, активными пользовательскими сессиями, текущей длиной очереди или последними сигналами активности устройств), где необходимо сразу видеть самые свежие данные.
- Данные событий, которые вы передаёте в другие инструменты с минимальными преобразованиями (необработанные данные с небольшой нормализацией, например приведением имён полей к единому виду или добавлением нескольких справочных полей).
Если логика преобразований становится сложнее, от данных зависят несколько команд или вам нужен более точный контроль затрат и производительности, переходите на инкрементальные модели или динамические таблицы / материализованные представления. Оставьте этот подход для самых небольших сценариев, наиболее чувствительных к задержке.
Предположения
Примеры на этой странице предполагают следующую конфигурацию:
- Внешняя по отношению к dbt система (ETL, потоковый конвейер, приложение) уже записывает данные в таблицу хранилища, например
raw.realtime_eventsилиops.active_sessions, и эта таблица соответствует вашему соглашению об уровне обслуживания в части задержки. - Прямые запросы к этой таблице приемлемы с точки зрения производительности и стоимости при ожидаемом количестве одновременных запросов.
- Вам не нужно, чтобы dbt сохранял промежуточные таблицы; для вас важны прежде всего:
- Единообразная логика SQL (именование столбцов, приведение типов)
- Тесты, контракты и происхождение данных
- Exposures для BI-инструментов и других потребителей данных
Все модели dbt в этом подходе материализуются как представления, а не как таблицы или инкрементальные модели.
Пример реализации
Ниже приведён пример реализации подхода на основе только представлений со следующей структурой:
- Исходная таблица (непрерывно обновляется):
raw.realtime_events - Легковесное представление промежуточного слоя:
analytics.stg_realtime_events_v - Представление предметной области:
analytics.vw_realtime_events_enriched
Определение исходной таблицы
# models/sources.yml
version: 2
sources:
- name: raw
schema: raw
tables:
- name: realtime_events
description: "Непрерывно обновляемая таблица событий из потокового конвейера."
loaded_at_field: event_ts
Представление промежуточного слоя
-- models/staging/stg_realtime_events.sql
{{ config(
materialized = 'view'
) }}
select
event_id,
event_ts::timestamp_ntz as event_ts, -- Синтаксис Snowflake для приведения типов
to_date(event_ts) as event_date,
user_id,
event_type,
payload
from {{ source('raw', 'realtime_events') }};
Определение представления предметной области
-- models/marts/vw_realtime_events_enriched.sql
{{ config(
materialized = 'view'
) }}
with base as (
select *
from {{ ref('stg_realtime_events') }}
),
user_dim as (
select
user_id,
user_segment,
signup_date
from {{ ref('dim_user') }} -- может быть таблицей или инкрементальной моделью
)
select
b.event_id,
b.event_ts,
b.event_date,
b.user_id,
u.user_segment,
b.event_type,
b.payload
from base as b
left join user_dim as u
on b.user_id = u.user_id;
Инструменты-потребители запрашивают analytics.vw_realtime_events_enriched. Пока raw.realtime_events непрерывно обновляется, эта цепочка представлений обеспечивает ту же актуальность данных, что и источник.
Преимущества
- Максимальная актуальность: представление отражает новые данные сразу после их поступления в
raw.realtime_events. - Простота эксплуатации: не нужно настраивать инкрементальную логику и запускать дополнительное задание dbt только ради поддержания актуальности данных. При этом задания для тестов, документации и других задач по-прежнему нужно запускать по расписанию.
- Оптимально для небольших наборов данных: подход хорошо работает с небольшими таблицами и простыми запросами. Вычисление представления на лету выполняется быстро и с небольшими затратами.
Ограничения и риски
Этот подход безопасен только при соблюдении строгих условий и имеет несколько важных ограничений:
- Не масштабируется для ресурсоёмких преобразований
- Нет «зафиксированных» промежуточных таблиц
- Чувствительность к изменениям схемы
- Возможное влияние на операционные системы
Не масштабируется для ресурсоёмких преобразований
Если логика усложняется и включает соединения больших таблиц, длинные цепочки представлений или ресурсоёмкие агрегации, вы быстро столкнётесь с проблемами производительности:
- Каждый запрос должен заново выполнять всю логику.
- Хранилищу приходится каждый раз оптимизировать и выполнять всю цепочку представлений.
В таких случаях используйте один из следующих вариантов:
- Инкрементальные модели
- Динамические таблицы или материализованные представления, если они подходят для вашей задачи
Нет «зафиксированных» промежуточных таблиц
Поскольку всё реализовано в виде представлений:
- Нет сохранённого промежуточного слоя для отладки или профилирования данных.
- Нельзя легко «повторно выполнить вчерашнюю логику», если вышестоящие данные изменились: всё всегда отражает текущее состояние.
Чувствительность к изменениям схемы
Изменения схемы исходной таблицы немедленно распространяются по всей цепочке представлений, что:
- Может нарушить работу BI-инструментов, использующих эти данные, при удалении столбцов или изменении типов.
- Повышает важность тестов и контрактов моделей, поскольку нет границы между пакетными обработками, на которой можно обнаружить проблемы до того, как с ними столкнутся пользователи.
Возможное влияние на операционные системы
Если непрерывно обновляемый источник сам является рабочей операционной базой данных (а не таблицей приёма данных в хранилище), важно не перегрузить его аналитическими запросами. В большинстве случаев рекомендуется:
- Сначала реплицировать данные в таблицу хранилища (Snowflake, BigQuery, Databricks и т. д.).
- Применять этот подход на основе только представлений внутри хранилища, а не непосредственно в системе оперативной обработки транзакций (OLTP).