Качество данных — зачем и как проверять¶
Данные в хранилище могут быть неполными, устаревшими или просто неправильными. Без проверок эти проблемы доходят до дашбордов и отчётов — и тогда бизнес принимает решения на основе мусора.
Что бывает без проверок¶
| Проблема в данных | Последствие |
|---|---|
| Дубликаты заказов | Выручка в отчёте завышена в 2 раза |
NULL в поле region |
Дашборд показывает пустую карту |
Статус 'test' в продуктовых данных |
Метрики конверсии искажены |
| Данные не обновились за сутки | Аналитик строит прогноз на вчерашних числах |
| Цена = −100 | Финансовый отчёт уходит в минус |
Стоимость ошибки растёт по цепочке
Ошибка в staging-таблице → неправильный расчёт в intermediate → искажённая витрина → неверный дашборд → бизнес-решение на плохих данных. Чем раньше поймаешь — тем дешевле исправить.
6 измерений качества данных¶
Data Management Body of Knowledge (DMBOK) выделяет шесть ключевых измерений. Каждое отвечает на свой вопрос о данных.
1. Completeness — полнота¶
Вопрос: Все ли данные на месте?
Проверяешь, что обязательные поля заполнены и нет пропущенных записей.
-- Сколько заказов без региона?
SELECT COUNT(*) AS missing_region
FROM orders
WHERE region IS NULL;
| missing_region |
|---|
| 342 |
Проверяй не только NULL
Пустая строка '', значение 'N/A' или 'unknown' — тоже пропуски. WHERE region IS NULL OR region = '' OR region = 'N/A'.
2. Accuracy — точность¶
Вопрос: Данные соответствуют реальности?
Проверяешь, что значения правдоподобны и попадают в допустимый диапазон.
-- Есть ли заказы с отрицательной ценой?
SELECT order_id, total_amount
FROM orders
WHERE total_amount < 0;
| order_id | total_amount |
|---|---|
| 98431 | −100.00 |
-- Возраст пользователей в разумном диапазоне?
SELECT user_id, age
FROM users
WHERE age < 0 OR age > 150;
3. Consistency — согласованность¶
Вопрос: Одни и те же данные не противоречат друг другу?
Проверяешь, что связанные таблицы и поля не конфликтуют.
-- Заказы, где дата доставки раньше даты создания
SELECT order_id, created_at, delivered_at
FROM orders
WHERE delivered_at < created_at;
-- Сумма позиций не совпадает с итогом заказа
SELECT
o.order_id,
o.total_amount AS order_total,
SUM(oi.qty * oi.price) AS calculated_total
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
GROUP BY o.order_id, o.total_amount
HAVING o.total_amount != SUM(oi.qty * oi.price);
4. Timeliness — своевременность¶
Вопрос: Данные достаточно свежие?
Проверяешь, что ETL-процессы работают и данные обновляются вовремя.
| last_update |
|---|
| 2026-03-31 08:15:00 |
Если сейчас 2 апреля — данные отстают на 2 дня. Это проблема.
Source freshness в dbt
dbt умеет автоматически проверять свежесть источников через dbt source freshness. Настраиваешь пороги warn_after и error_after — dbt сам сообщит, если данные устарели.
5. Validity — валидность¶
Вопрос: Данные соответствуют формату и правилам?
Проверяешь, что значения из допустимого множества, форматы корректны.
-- Статусы, которых не должно быть
SELECT DISTINCT status
FROM orders
WHERE status NOT IN ('paid', 'pending', 'cancelled', 'refunded');
| status |
|---|
| test |
| PAID |
-- Email без @ — невалидный формат
SELECT user_id, email
FROM users
WHERE email NOT LIKE '%@%.%';
6. Uniqueness — уникальность¶
Вопрос: Нет ли дубликатов?
Проверяешь, что первичные ключи действительно уникальны.
-- Дубликаты order_id
SELECT order_id, COUNT(*) AS cnt
FROM orders
GROUP BY order_id
HAVING COUNT(*) > 1;
| order_id | cnt |
|---|---|
| 12345 | 3 |
| 67890 | 2 |
Дубликаты — самая частая проблема
Неправильный JOIN, повторная загрузка, отсутствие дедупликации — всё это создаёт дубли. Тест unique на первичный ключ — обязательный минимум для каждой таблицы.
Обзор измерений¶
| Измерение | Вопрос | Типичная проверка |
|---|---|---|
| Completeness | Всё ли на месте? | NOT NULL, подсчёт пропусков |
| Accuracy | Данные правдивы? | Диапазоны значений, сравнение с источником |
| Consistency | Нет противоречий? | Сравнение связанных таблиц и полей |
| Timeliness | Данные свежие? | Проверка MAX(updated_at), source freshness |
| Validity | Формат корректен? | Допустимые значения, regex |
| Uniqueness | Нет дубликатов? | GROUP BY ... HAVING COUNT(*) > 1 |
Инструменты проверки качества¶
dbt tests¶
Встроенные тесты dbt — самый простой способ начать. Четыре теста «из коробки» покрывают базовые проверки:
models:
- name: stg_orders
columns:
- name: order_id
tests:
- unique
- not_null
- name: status
tests:
- accepted_values:
values: ['paid', 'pending', 'cancelled', 'refunded']
- name: user_id
tests:
- relationships:
to: ref('stg_users')
field: user_id
Плюсы: интегрирован в dbt-пайплайн, нулевая настройка, YAML-конфигурация. Минусы: только SQL-проверки, нет профилирования данных, ограниченная отчётность.
Great Expectations (GX)¶
Фреймворк для валидации данных на Python. Expectations — декларативные правила, которые можно применять к DataFrame, SQL-таблице или файлу.
import great_expectations as gx
context = gx.get_context()
validator = context.sources.pandas_default.read_csv("orders.csv")
validator.expect_column_values_to_not_be_null("order_id")
validator.expect_column_values_to_be_between("total_amount", min_value=0)
validator.expect_column_values_to_be_in_set(
"status", ["paid", "pending", "cancelled", "refunded"]
)
results = validator.validate()
Плюсы: 300+ встроенных expectations, Data Docs (автодокументация), интеграция с Airflow. Минусы: сложная настройка, Python-зависимость, тяжёлый для небольших проектов.
Soda¶
Инструмент мониторинга данных с YAML-конфигурацией и облачным дашбордом.
# checks/orders.yml
checks for orders:
- row_count > 0
- missing_count(order_id) = 0
- duplicate_count(order_id) = 0
- invalid_count(status) = 0:
valid values: ['paid', 'pending', 'cancelled', 'refunded']
- freshness(updated_at) < 24h
Плюсы: простой YAML-синтаксис, встроенная проверка свежести, облачный мониторинг. Минусы: облачная версия платная, меньше гибкости чем GX.
Сравнение инструментов¶
| Критерий | dbt tests | Great Expectations | Soda |
|---|---|---|---|
| Язык проверок | YAML + SQL | Python | YAML |
| Встроенных проверок | 4 (+ пакеты) | 300+ | 25+ |
| Интеграция с dbt | Нативная | Через пакет | Через CLI |
| Отчётность | Терминал | Data Docs (HTML) | Облачный дашборд |
| Порог входа | Низкий | Средний | Низкий |
| Стоимость | Бесплатно | Бесплатно (OSS) | Freemium |
| Лучше всего для | dbt-проекты | Python-пайплайны | Мониторинг в проде |
Как выбрать подход¶
Есть dbt-проект?
├── Да → Начни с dbt tests (unique, not_null, accepted_values)
│ Нужно больше? → Добавь dbt-expectations (пакет с 50+ тестами)
│ Нужен мониторинг? → Подключи Soda или Elementary
└── Нет
├── Python-пайплайн → Great Expectations
└── Нужен быстрый мониторинг → Soda
Начни с малого
Не пытайся покрыть тестами всё сразу. Начни с трёх проверок на каждую ключевую таблицу: unique на PK, not_null на обязательные поля, accepted_values на статусы. Остальное добавляй по мере обнаружения проблем.
Что запомнить¶
- 6 измерений качества: полнота, точность, согласованность, своевременность, валидность, уникальность
- Каждое измерение — конкретная SQL-проверка, которую можно автоматизировать
- dbt tests — минимальный порог входа, встроен в пайплайн
- Great Expectations — мощный фреймворк для Python-стека
- Soda — мониторинг с YAML и облачным дашбордом
- Начни с
unique+not_nullна ключевые таблицы — это уже лучше, чем ничего
Проверь себя¶
Что дальше?¶
Теперь, когда ты понимаешь что проверять, разберись с Great Expectations — как настроить автоматическую валидацию данных на Python.
Источники¶
- DAMA DMBOK: Data Quality — фреймворк 6 измерений качества данных
- dbt Documentation: Data tests — встроенные тесты dbt
- Great Expectations Documentation — фреймворк валидации данных
- Monte Carlo: What is Data Observability — обзор наблюдаемости данных