Валидация данных в аналитике
Зачем валидировать данные
Плохие данные → неправильные выводы → неправильные решения → потерянный бизнес.
Типичные последствия:
- «Revenue вырос на 20%» → на самом деле ETL добавил дубликаты.
- «DAU упал» → сломался трекер push-ей.
- «A/B-тест значим» → SRM — сплит нечестный.
Шесть направлений валидации
1. Completeness (полнота)
Все ли данные пришли? Нет ли пропусков?
-- Доля NULL в ключевой колонке
SELECT
COUNT(*) FILTER (WHERE email IS NULL) * 100.0 / COUNT(*) AS null_pct
FROM users;- OK: стабильный % NULL.
- Alert: скачок NULL вверх.
2. Uniqueness (уникальность)
Дубликаты где их не должно быть?
-- Ожидаем уникальных email
SELECT email, COUNT(*) FROM users
GROUP BY email HAVING COUNT(*) > 1;3. Validity (корректность)
Значения в допустимом диапазоне?
-- Возраст должен быть 0–120
SELECT * FROM users WHERE age < 0 OR age > 120;
-- Email должен соответствовать паттерну
SELECT * FROM users WHERE email NOT ~ '^[^@]+@[^@]+\.[^@]+$';
-- Статус только из списка
SELECT * FROM orders WHERE status NOT IN ('paid', 'pending', 'refunded');4. Consistency (консистентность)
Данные в разных местах согласованы?
-- Заказы без соответствующих пользователей (orphan records)
SELECT * FROM orders o
WHERE NOT EXISTS (SELECT 1 FROM users WHERE user_id = o.user_id);
-- Сверка итогов
SELECT
(SELECT SUM(amount) FROM orders WHERE status = 'paid') AS db_total,
(SELECT SUM(amount) FROM mart_revenue_daily) AS mart_total;5. Timeliness (своевременность)
Данные свежие?
-- Последняя запись не старше 1 часа
SELECT MAX(created_at) AS last_event FROM events;
-- Алерт если отставание > 2 часов6. Accuracy (точность)
Соответствуют ли данные реальности?
Самое сложное — требует сверки с внешним источником:
- Revenue в БД vs deposits в банке.
- Количество пользователей в dashboard vs в CRM.
Если хочется сразу закрепить тему на практике — открой тренажёр в Telegram. 10 минут в день — и синтаксис в пальцах.
Автоматические проверки
dbt tests
models:
- name: fct_orders
columns:
- name: order_id
tests:
- unique
- not_null
- name: amount
tests:
- not_null
- dbt_utils.accepted_range:
min_value: 0Great Expectations
Python library для data validation:
import great_expectations as ge
df_ge = ge.from_pandas(df)
df_ge.expect_column_values_to_not_be_null('user_id')
df_ge.expect_column_values_to_be_between('age', 0, 120)
df_ge.expect_column_values_to_be_unique('email')Airflow sensors и checks
from airflow.operators.python import PythonOperator
def check_data_quality():
hook = PostgresHook()
null_pct = hook.get_first('...')[0]
if null_pct > 0.1:
raise ValueError(f'Too many nulls: {null_pct}')
check = PythonOperator(
task_id='data_quality_check',
python_callable=check_data_quality
)Практические проверки по таблицам
users
-- Дубликаты по email
SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1;
-- Невалидные email
SELECT * FROM users WHERE email NOT ~ '^[^@]+@[^@]+\\.[^@]+$';
-- Registered_at из будущего
SELECT * FROM users WHERE registered_at > NOW();orders
-- Amount отрицательный?
SELECT * FROM orders WHERE amount < 0;
-- User_id не существует
SELECT * FROM orders o
WHERE NOT EXISTS (SELECT 1 FROM users WHERE user_id = o.user_id);
-- Status не из списка
SELECT DISTINCT status FROM orders
WHERE status NOT IN ('paid', 'pending', 'refunded', 'cancelled');events
-- Event_time старше 1 года
SELECT * FROM events WHERE event_time < NOW() - INTERVAL '1 year';
-- Пиковые bots (много событий за секунду)
SELECT user_id, COUNT(*) FROM events
WHERE event_time > NOW() - INTERVAL '1 minute'
GROUP BY user_id HAVING COUNT(*) > 100;Мониторинг и алерты
Что мониторить
- Количество записей в ключевых таблицах (растёт/падает?).
- % NULL в важных колонках.
- Последний timestamp (lag).
- Ошибки ETL в логах.
Где настраивать
- Airflow: DAG с ежедневной проверкой + alert в Slack.
- dbt:
dbt testв CI/CD, fail pipeline при проблемах. - Great Expectations: notebook с checks, выполняется по расписанию.
- Grafana/Datadog: dashboard с data-quality метриками.
Пример алерта
def alert_null_spike():
today = get_null_pct('email')
yesterday = get_null_pct_yesterday('email')
if today > yesterday * 2:
slack_notify(f'NULL spike in users.email: {today}%')Чтобы не только читать теорию, но и решать реальные задачи — загляните в бот Карьерника. Там по каждой теме подборка вопросов с разборами.
Data Contract
Современная практика — contract между producer и consumer данных:
- Formal schema (колонки, типы).
- SLA (latency, freshness).
- Тесты (validity, uniqueness).
Инструменты: dbt Contract, Soda Core, Monte Carlo.
Читайте также
- Качество данных для аналитика
- Data Governance
- Как очистить данные в pandas
- dbt шпаргалка
- Как найти выбросы
FAQ
Кто отвечает за валидацию — аналитик или DE?
Совместно. DE — за pipeline и infrastructure. Аналитик — за business-логику и корректность метрик.
Как часто запускать проверки?
Продакшн-критичные — ежедневно. Остальные — еженедельно. Для real-time ETL — при каждом batch.
dbt или Great Expectations?
dbt — если есть dbt pipeline. GE — независимо. Совместимы.
Что важнее — uniqueness или completeness?
Зависит от контекста. PK duplicate может сломать JOIN → большая проблема. NULL в описательной колонке — меньшая.