Качество данных и валидация

Урок учит проверять данные внутри конвейера, чтобы мусор не доехал до отчётов.

Валидация данных — автоматические проверки качества данных на каждом этапе конвейера: схема, диапазоны значений, уникальность, полнота, свежесть.

Принцип «упасть громко»

Худшее, что может сделать конвейер, — тихо загрузить битые данные. Аналитик увидит красивый дашборд с неверными цифрами и примет неверное решение. Поэтому хороший пайплайн при плохих данных останавливается и кричит, а не продолжает молча. Лучше задержать отчёт на час, чем выдать ложь.

У этого принципа есть и техническое имя — circuit breaker (предохранитель): задача-проверка стоит между этапами и «размыкает цепь», если данные не прошли контроль. Конвейер останавливается, приходит алерт, инженер разбирается. Да, это означает, что иногда отчёт выйдет с задержкой. Но доверие к данным — главный актив, и один раз показанная неверная цифра подрывает его сильнее, чем десять задержек.

Виды проверок

ПроверкаПример
Схемаесть все нужные столбцы, верные типы
Диапазонывозраст 0–120, сумма ≥ 0
Уникальностьid заказа не повторяется
Полнотанет пропусков в ключевых полях
Свежестьданные не старше суток

Как работает под капотом

Простой валидатор на чистом Python: проверяет диапазон, полноту и уникальность, собирает ошибки. Если ошибки есть — задача в конвейере должна упасть.

rows = [
    {"id": 1, "amount": 300},
    {"id": 2, "amount": -5},     # отрицательная сумма
    {"id": 2, "amount": 100},    # дубль id
]
errors = []
seen = set()
for r in rows:
    if r["amount"] < 0:
        errors.append(f"id={r['id']}: отрицательная сумма")
    if r["id"] in seen:
        errors.append(f"id={r['id']}: дубликат ключа")
    seen.add(r["id"])

if errors:
    print("Валидация провалена:")
    for e in errors:
        print(" -", e)
else:
    print("OK")

Вывод:

Валидация провалена:
 - id=2: отрицательная сумма
 - id=2: дубликат ключа

То же на SQL — проверка свежести и аномалий запросом-«стражем»: если он вернул строки, данные подозрительны.

CREATE TABLE orders (id INTEGER PRIMARY KEY, amount INTEGER);
INSERT INTO orders VALUES (1, 300), (2, -5), (3, 0);

-- страж качества: ищем некорректные суммы
SELECT id, amount FROM orders WHERE amount <= 0;

Приём «запрос-страж» очень удобен: вы пишете SELECT, который возвращает только проблемные строки, и считаете их. Если счётчик больше нуля — данные не прошли проверку, задача падает. Так устроены многие инструменты тестирования данных, например тесты в dbt: каждый тест — это, по сути, запрос, который должен вернуть ноль строк. Этот подход позволяет описывать правила качества декларативно, на привычном SQL, и держать их рядом с самими моделями данных.

Частые ошибки

  • Проверять данные только в конце. Битые данные надо ловить как можно раньше, сразу после извлечения, чтобы не тратить ресурсы на обработку мусора.
  • Логировать ошибку, но продолжать. Если проверка нашла проблему, задача должна упасть и остановить конвейер, а не записывать предупреждение и грузить дальше.
  • Забыть про свежесть. Технически валидные, но устаревшие данные так же опасны, как и битые.

Итог

  • Валидация ловит проблемы качества: схема, диапазоны, дубли, полнота, свежесть.
  • При плохих данных конвейер должен падать, а не тихо грузить мусор.
  • Проверки ставят как можно раньше, сразу после извлечения.
Проверьте себя
1. Как должен вести себя конвейер, если валидация нашла битые данные?
AТихо загрузить их и записать предупреждение
BОстановиться и подать сигнал об ошибке
CУдалить всю таблицу
DПродолжить, исправив данные наугад
2. Почему проверку свежести данных тоже относят к валидации?
AСвежесть не важна для аналитики
BУстаревшие данные могут быть технически корректны, но вести к неверным решениям
CСвежесть проверяет только скорость запроса
DЭто часть оптимизации хранилища