Data freshness (свежесть данных) — это метрика, которая показывает, насколько данные в хранилище отстают от реального момента события. Считается как лаг между временем, когда событие произошло, и временем, когда оно стало доступно для запроса: Лаг = now() − max(event_time). Если лаг превышает SLA (например, 2 часа), данные считаются устаревшими, и отчёты на них могут вводить в заблуждение. На собеседовании аналитика freshness — частый вопрос в блоке «качество данных», потому что именно несвежие данные ломают дашборды и решения.
Аналитик, который умеет объяснить, что такое лаг, как задать SLA и написать SQL-проверку свежести, выглядит на голову выше кандидата, который знает только «джойны и группировки». Разберём тему так, как её ждут на интервью в Яндексе, Озоне и Сбере.
Что такое data freshness и зачем её мерить?
Свежесть данных — это разрыв во времени между тем, когда что-то случилось в продукте, и тем, когда аналитик может это увидеть в таблице. Допустим, пользователь оформил заказ в 14:00, а строка о заказе попала в витрину только в 16:30. Лаг — 2 часа 30 минут.
Почему это критично:
- Решения на устаревших данных — продакт смотрит конверсию «за сегодня», но данные обновились вчера ночью. Вывод о росте ложный.
- Алерты не срабатывают — система мониторинга метрик ждёт свежих чисел, а их нет. Падение выручки замечают через сутки.
- Доверие к данным — если витрина «иногда отстаёт», команда перестаёт ей верить и считает всё в Excel вручную.
Freshness — одно из шести классических измерений качества данных наряду с полнотой, точностью, консистентностью, валидностью и уникальностью. Но именно свежесть проще всего автоматизировать SQL-проверкой.
Как считать лаг свежести: формулы
Есть два разных лага, и их важно не путать на собесе.
1. Event-to-availability лаг (бизнесовый). Разница между временем события и временем его появления в таблице:
freshness_lag = load_time − event_time
2. Lag «от текущего момента» (операционный). Насколько устарела самая свежая запись прямо сейчас:
staleness = now() − max(event_time)
Первый отвечает на вопрос «как быстро данные доезжают», второй — «можно ли строить отчёт прямо сейчас». Для мониторинга чаще берут второй.
| Метрика | Формула | О чём говорит |
|---|---|---|
| Freshness lag | load_time − event_time | Скорость доставки данных в пайплайне |
| Staleness | now() − max(event_time) | Насколько устарела витрина в моменте |
| Median lag | percentile(lag, 0.5) | Типичная задержка без выбросов |
| p95 lag | percentile(lag, 0.95) | Хвост задержек для SLA |
На практике для SLA берут не среднее, а перцентили: среднее легко искажается одним зависшим батчем. Если 95% записей доезжают за 30 минут — это честная картина.
Что такое SLA для свежести и как его задать?
SLA (Service Level Agreement) для freshness — это договорённость о максимально допустимом лаге. Формулируется просто: «данные в витрине orders_mart не старше 2 часов в рабочее время».
Как выбрать порог:
- От бизнес-потребности. Оперативный дашборд для саппорта — лаг до 15 минут. Месячный финансовый отчёт — лаг до суток допустим.
- От частоты загрузки. Если батч идёт раз в час, SLA не может быть меньше часа + время обработки. Реалистичный порог —
интервал_загрузки × 1.5. - От стоимости свежести. Стриминг каждую минуту дороже, чем батч раз в час. SLA — баланс между ценой инфраструктуры и пользой.
Различают три уровня:
- Target — цель, к которой стремимся (лаг ≤ 30 мин).
- SLO — внутренний объект (95% времени лаг ≤ 1 час).
- SLA — внешнее обязательство с последствиями (лаг ≤ 2 часа, иначе инцидент).
На собесе хороший ответ звучит так: «Я бы задал SLA от потребителя данных: для real-time саппорта — минуты, для аналитики — часы, и измерял бы p95, а не среднее».
Как написать SQL-мониторинг свежести?
Базовая проверка staleness одной таблицы — посчитать разницу между текущим временем и максимальным временем события:
SELECT now() − MAX(event_time) AS staleness FROM orders;
Чтобы сразу получить флаг нарушения SLA (порог 2 часа = 7200 секунд):
SELECT MAX(event_time) AS last_event, EXTRACT(EPOCH FROM (now() − MAX(event_time))) / 3600 AS lag_hours, CASE WHEN now() − MAX(event_time) > INTERVAL '2 hours' THEN 'STALE' ELSE 'FRESH' END AS status FROM orders;
Для пайплайна с явным временем загрузки считаем распределение лага по строкам:
SELECT date_trunc('hour', load_time) AS load_hour, COUNT(*) AS rows_loaded, AVG(EXTRACT(EPOCH FROM (load_time − event_time))) / 60 AS avg_lag_min, MAX(EXTRACT(EPOCH FROM (load_time − event_time))) / 60 AS max_lag_min FROM events GROUP BY 1 ORDER BY 1 DESC;
Чтобы проверять много витрин разом, удобно завести метатаблицу с порогами и джойнить её с фактическими максимумами:
SELECT t.table_name, t.sla_hours, EXTRACT(EPOCH FROM (now() − f.last_event)) / 3600 AS actual_lag_hours FROM freshness_sla t JOIN freshness_facts f ON t.table_name = f.table_name WHERE now() − f.last_event > t.sla_hours * INTERVAL '1 hour';
Этот запрос вернёт только те таблицы, которые нарушили SLA, — готовый вход для алерта. Потренироваться писать такие проверки можно прямо в браузере в SQL-тренажёре, где есть PostgreSQL и SQLite с разбором решений.
Как настроить алерты по свежести данных?
Сам по себе SQL-запрос ничего не оповещает — нужен механизм, который запускает проверку и сигнализирует о нарушении. Типовая схема:
- Шедулер (Airflow, cron, dbt) каждые N минут гоняет freshness-запрос.
- Результат пишется в таблицу мониторинга со статусом FRESH / STALE.
- Триггер: если статус STALE — отправка в Telegram, почту или дежурный канал.
- Дедупликация: не слать алерт каждые 5 минут, пока инцидент не закрыт.
Полезные практики для алертов:
- Алерт по тренду, а не только по порогу. Лаг плавно растёт с 10 до 90 минут — это сигнал деградации до пробоя SLA.
- Учёт расписания. Ночью лага в 3 часа может быть норма (батч идёт утром). Алерт настраивают на рабочие окна.
- Разделение severity. Warning при p95 > SLO, critical при p95 > SLA.
В dbt для этого есть встроенный тест source freshness: задаёшь loaded_at_field и пороги warn_after / error_after, и инструмент сам проверяет лаг при каждом запуске. Это стандарт де-факто для современных команд.
Какие ошибки чаще всего разбирают на собесе?
- Путают event_time и load_time. Лаг считают от времени загрузки до текущего момента — получают ноль и думают, что данные свежие.
- Берут AVG вместо p95. Один зависший батч раздувает среднее, и команда не видит реальную картину хвоста.
- Не учитывают часовые пояса.
event_timeв UTC, аnow()в локальной зоне — лаг скачет на несколько часов. - Считают только max и не смотрят на пропуски. Витрина «свежая» по последней строке, но за обед вообще не было загрузок — данные с дырой.
- SLA «из головы». Порог не привязан к потребителю и частоте загрузки — либо вечные ложные алерты, либо инциденты замечают поздно.
Хороший кандидат проговаривает: «Freshness — это не одно число, а распределение лага, привязанное к SLA конкретного потребителя, с алертом по p95».
Где потренироваться
Свежесть данных лучше всего закрепляется на практике — счёт лага, написание мониторинга и формулировка SLA на реальных кейсах.
- Тренажёр метрик — разбери data freshness рядом с другими метриками качества и продукта: определение, формула, как объяснять на собесе.
- SQL-тренажёр — напиши запросы на staleness, распределение лага и проверку SLA по метатаблице. Настоящий PostgreSQL и SQLite в браузере с автопроверкой.
- Тестовые задания — реши задачи на мониторинг качества данных и SLA в формате реальных собеседований аналитика.
Свежесть данных — недооценённая, но мощная тема: она показывает, что ты думаешь не только про SQL, но и про надёжность данных, на которых строятся решения. Освой формулу лага, перцентили и SLA — и блок «качество данных» на собесе перестанет быть лотереей.