Кто ответит за качество аналитики: QA для Хранилища Данных

от автора

Поверь своим глазам и тому что видишь на Дашборде

Мы в Wheely в значительной степени опираемся на данные при принятии операционных и стратегических решений. От выплаты еженедельных бонусов партнерам до экспансии в другие города и страны.

Каждый менеджер или Product Owner досконально знает свою область и любые отклонения могут вызвать вопросы. Поэтому к достоверности дашбордов и метрик предъявляются повышенные требования. А мы в команде Аналитики стремимся идентифицировать и исправить проблемы раньше, чем они попадут в отчетность. 

Как известно, легче предотвратить, и поэтому я решил подойти к проблеме системно и проактивно. И, конечно, первым делом создал канал в Slack, в который настроил доставку уведомлений о любых ошибках в наших пайплайнах.

Уверенность в актуальности витрин данных

Прежде всего мы хотим убедиться в том, что пользовательские витрины содержат актуальные на момент времени данные:

  • К 10 утра каждого дня у нас рассчитаны витрины за полные прошлые сутки

  • Чтение из источников идет в ногу со временем и отставание не превышает 8 часов

  • Все источники продолжают слать лог изменений в DWH

Выходит, задача QA формулируется следующим образом:

  • Покажи мне все витрины данных, в которых время актуальности отстает от ожидаемого

Реализация для Хранилища:

  • В конфигурационном файле .yml добавим параметр freshness:

freshness:    warn_after: {count: 4, period: hour}    error_after: {count: 8, period: hour}  loaded_at_field: "__etl_loaded_at"

  • Для каждого теста будет выполнен простой шаблонизированный SQL-запрос:

select  max({{ loaded_at_field }}) as max_loaded_at,  {{ current_timestamp() }} as snapshotted_at from {{ source }} where {{ filter }}

  • Собранные метрики можно визуализировать в сводный отчет:

Мониторинг метрик расчета Витрин Данных

Неминуемо при проектировании сложных витрин, кубов, будут возникать проблемные места:

  • Баги и просчеты в формулах расчета метрик

  • Неожиданные данные (edge cases), которые могут нарушать заложенную логику

  • Бутылочное горлышко (bottleneck) в операциях расчетов

Они могут привести к серьезным последствиям:

  • Ошибки: Таймаут, Out of Memory, Disk Full

  • Замедление всего пайплайна загрузок и расчетов и нарушение SLA

Для контроля можно собирать следующие метрики:

  • Время, затраченное на формирование витрины + его динамика (скачки времени расчета)

  • Потребление ресурсов CPU

  • Потребление ресурсов диска и сети — IO, network

Лидеры этого рейтинга становятся первыми кандидатами на оптимизацию и рефакторинг.

Задача формулируется следующим образом:

  • Покажи мне те витрины, формирование которых требует излишне много ресурсов

Реализация для Хранилища:

  • Снять метрики расчетов витрин

  • Отрисовать дашборд

  • Настроить алерты

+pre-hook: "{{ logging.log_model_start_event() }}" +post-hook: "{{ logging.log_model_end_event() }}"

Валидация схемы данных в основе тестирования

Современные Хранилища предполагают структуру, строгую типизацию, поколоночное хранение и компрессию данных. Структура данных суть схема — набор атрибутов, их типов, ограничений, например, PRIMARY KEY, FOREIGN KEY, NOT NULL, UNIQUE.

Большинство DWH не предполагает валидацию ограничений на этапе записи. Это нужно скорее в рамках подсказок оптимизатору запросов. Т.е. Это всего лишь предположение о данных, а фактическая проверка остается на откуп инженерам и аналитикам.

Какие базовые ожидания можем иметь относительно данных:

  • Есть ли в данных пропуски (NULL) там, где их быть не должно?

  • Какова атомарность моих данных (UNIQUE ID строки)?

  • Как таблицы соотносятся между собой (PRIMARY — FOREIGN KEYS)?

  • Есть ли записи, выходящие из списка допустимых значений(ACCEPTED VALUES)?

Задача QA формулируется следующим образом:

  • Покажи мне те витрины и источники, данные в которых нарушают наши ожидания

Реализация для Хранилища:

  • В конфигурационном файле .yml добавим параметр tests:

- name: dim_cars      description: Wheely partners cars.      columns:          - name: car_id            tests:                - not_null                - unique          - name: status            tests:                - not_null                - accepted_values:                    values: ['deleted', 'unknown', 'active', 'end_of_life', 'pending', 'rejected'                            , 'blocked', 'expired_docs', 'partner_blocked', 'new_partner']   

  • Для каждого теста будет выполнен простой шаблонизированный SQL-запрос

-- NOT NULL test select count(*) as validation_errors from "wheely"."dbt_test"."dim_cars" where car_id is null   -- UNIQUE test select count(*) as validation_errors from (    select        car_id    from "wheely"."dbt_test"."dim_cars"    where car_id is not null    group by car_id    having count(*) > 1 ) validation_errors   -- ACCEPTED VALUES test with all_values as (    select distinct        status as value_field    from "wheely"."dbt_test"."dim_cars" ), validation_errors as (    select        value_field    from all_values    where value_field not in (        'deleted','unknown','active','end_of_life','pending','rejected','blocked','expired_docs','partner_blocked','new_partner'    ) ) select count(*) as validation_errors from validation_errors

Бизнес-логика тоже подлежит проверке

Использую термин бизнес-логика в широком смысле — это любая сколь угодно сложная логика расчетов и взаимосвязей, которую мы закладываем в витрины данных. По сути это и есть бизнес-требования, лежащие в основе формирования Витрин.

Несколько простых примеров:

  • Сумма заказа не может быть отрицательной

  • Время подачи машины по заказу строго больше времени бронирования

  • Пользовательская сессия заканчивается только одним заказом, либо прерывается

  • Комиссия не превышает заданного %

Резкие скачки сумм (и вверх и вниз), неправдоподобные графики и значения метрик чаще всего становятся объектом пристального внимания на дашбордах и в отчетах.

Задача QA формулируется следующим образом:

  • Покажи мне те витрины данных, в которых нарушены бизнес-правила.

Реализация для Хранилища:

  • В терминах SQL выразить ту ситуацию, которая описывает нарушение правил

  • Сформировать тест на базе SQL-запроса

  • Тест считается пройденным (PASSED) если запрос возвращает 0 записей, и проваленным (FAILED) если записей >= 1

Continuous Integration на страже мастер-ветки DWH

Хорошо, идём дальше. Над DWH мы работаем совместно всей командой. Это подразумевает скоординированность и согласованность действий. Однако нередки случаи ошибок, просчеты, невнимательности на этапе разработки, которые приводят к ошибкам в PROD-окружении после PR Merge:

  • Доработка в одной части может послужить причиной ошибки в другой части

  • DEV-окружение инженера может отличаться от PROD-окружения

  • Запуск неоптимального кода на всех данных может привести к ошибке (например, Out of Memory)

Решение давно придумано — это использование практик тестирования в рамках Continuous Integration (CI). И его можно и нужно применять к данным!

Задача формулируется следующим образом:

  • Минимизировать вероятность появления ошибок в master-ветке и PROD-окружении DWH  после релизов.

Реализация для Хранилища:

  • Подготовить окружение для CI (например, актуальная копия PROD-окружения, содержащая только 7 последних дней)

  • Выполнить полный пересчет всех витрин и метрик без ошибок прежде чем дать возможность влить feature-ветку в master

Кросс-сверка состояния DWH и Источников

От Хранилища Данных мы ожидаем отображение актуального состояния (а также всей истории) источников данных:

  • Наличие в DWH всех записей, которые присутствуют в источнике

  • Точное соответствие значений атрибутов (статус, временные метки, метрики) один-к-одному

Мы хотели бы застраховаться от ситуаций, когда часть данных просто не попадает в Хранилище в силу технических причин, а также от потери изменений состояния записей (например, финализация статуса заказа или корректировка его стоимости).

Задача формулируется следующим образом:

  • Убедиться в том, что Хранилище находится в консистентном (согласованном) с источниками состоянии.

Эта задача имеет одну из самых сложных реализаций и может стать темой отдельной статьи, судите сами:

  • Определить набор атрибутов, подлежащих верификации: идентификаторы, внешние ключи, измерения (страна, город, статус), метрики (стоимость, продолжительность, комиссия).

  • Выгрузить все строки из источника, актуальные на текущий момент

  • Загрузить строки в DWH и подготовить логику сверок

  • Настроить визуализацию и уведомления

Визуальное представление с возможностью drill-down до уровня атомарных записей:

Собирая всё в единый пазл

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

  • Регулярный мониторинг, сбор и анализ метрик

  • Continuous Integration and Testing

  • Настройка уведомлений и алертов для команды

  • Проактивная работа над устранением инцидентов и причин ошибок

  • Управление ожиданиями пользователей в случае возникновения проблем (У нас всё под контролем)

В этой статье я показал подход к контролю качества данных, который мы выстраиваем в команде Wheely. Надеюсь, вы почерпнули для себя много нового и полезного.

Обширный набор тем, связанных с обработкой, хранением, тестированием данных изучается в рамках курса «Data Engineer» в OTUS, запуск которого состоится уже совсем скоро.

Как преподаватель курса я приглашаю вас 4 ноября в 20:00 на День Открытых Дверей курса «Data Engineer». Приходите на вебинары в OTUS знакомиться со мной и другими экспертами, будем ждать.

Что почитать еще

Напоследок я оставлю вам несколько ссылок на смежную тематику для дальнейшего изучения:

  1. Data Build Tool или что общего между Хранилищем Данных и Смузи — обзор DBT на русском языке

  2. The farm-to-table testing framework — комплексный подход к тестированию качества данных

  3. Tests — Related reference docs — раздел документации DBT, посвященный тестированию

  4. How to get started with data testing — тред на dbt discourse с обсуждением по теме

  5. Data testing: why you need it — взгляд на преимущества тестирования данных

  6. Manual Work is a Bug — несколько слов о принципах автоматизации и DRY

ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/526174/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *