Шесть измерений data quality
Данные плохого качества — главный враг любой аналитики. Если в orders.amount встречаются отрицательные значения, дашборд по выручке покажет странные числа. Если customer_id иногда NULL, JOIN с CRM “теряет” заказы. Если события приходят с опозданием в неделю — реал-тайм аналитика становится фикцией.
Чтобы говорить о data quality системно, индустрия выработала шесть измерений (dimensions): каждая описывает свой аспект “хорошести” данных. Знание этих шести измерений — must-have для junior DE.
Шесть DQ dimensions
Эту классификацию популяризовала DAMA (Data Management Association) в книге “DMBOK” и она стала стандартом в индустрии. Разные источники могут называть измерения иначе (например, “freshness” вместо “timeliness”), но смысл тот же.
Рассмотрим каждое измерение через примеры на гипотетической таблице orders.
1. Completeness (полнота)
Определение: все ли данные присутствуют, нет ли пропусков в обязательных полях.
В таблице orders обязательные поля: order_id, customer_id, amount, created_at, status. Пропуск в любом из них — проблема.
SQL-проверки:
-- Сколько строк с NULL в обязательных полях
SELECT
count(*) AS total_rows,
sum(case when order_id IS NULL then 1 else 0 end) AS missing_order_id,
sum(case when customer_id IS NULL then 1 else 0 end) AS missing_customer_id,
sum(case when amount IS NULL then 1 else 0 end) AS missing_amount,
sum(case when created_at IS NULL then 1 else 0 end) AS missing_created_at
FROM orders;
-- Процент полноты по колонке
SELECT
count(customer_id) * 100.0 / count(*) AS customer_id_completeness_pct
FROM orders;
Бизнес-влияние: если 5% заказов без customer_id, эти заказы выпадут из cohort-аналитики. Если 1% без amount — выручка занижена.
2. Accuracy (точность)
Определение: насколько данные соответствуют реальности. Это самое сложное измерение — для проверки нужен внешний источник истины.
Примеры проблем:
customer.email = "[email protected]"— это тестовый ввод, не реальный.order.amount = 0.00— это бесплатный заказ или ошибка?customer.country = "XX"— неизвестная страна.
SQL-проверки:
-- Тестовые email
SELECT count(*) FROM customers
WHERE email LIKE '%test%' OR email LIKE '%example%';
-- Заказы с нулевой суммой
SELECT count(*) FROM orders WHERE amount = 0;
-- Невалидные страны (если есть reference table)
SELECT count(*) FROM customers c
LEFT JOIN dim_countries dc ON c.country = dc.iso_code
WHERE dc.iso_code IS NULL;
Бизнес-влияние: маркетинг шлёт email на [email protected] — bounce-rate растёт, репутация sender’а падает.
3. Consistency (согласованность)
Определение: одинаковые данные согласованы между разными местами хранения. Если customer существует в orders.customer_id, он должен существовать в customers.id.
Примеры проблем:
orders.customer_id = 12345, но вcustomersтакого id нет.- В
customersстрана “United States”, вaddresses— “USA”. - В
revenue_daily.totalза 2026-05-17 одно значение, в источнике (Stripe) — другое.
SQL-проверки:
-- Orphan customer_id в orders
SELECT count(*)
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
WHERE c.id IS NULL;
-- Inconsistency между mart и source
WITH dwh_revenue AS (
SELECT sum(amount) AS rev FROM mart_revenue_daily WHERE day = '2026-05-17'
),
source_revenue AS (
SELECT sum(amount) AS rev FROM raw.orders
WHERE date_trunc('day', created_at) = '2026-05-17' AND status = 'paid'
)
SELECT
dwh_revenue.rev AS dwh,
source_revenue.rev AS source,
abs(dwh_revenue.rev - source_revenue.rev) AS diff
FROM dwh_revenue, source_revenue;
Бизнес-влияние: дашборд показывает revenue 1М USD, а финансы видят в источнике 1.1М. Доверие к данным разрушается.
SQL JOINs: LEFT JOIN для orphan-проверок и cross-system consistency4. Timeliness (своевременность)
Определение: насколько свежие данные относительно нужной частоты обновления.
Для daily-витрины: данные за вчерашний день должны появиться сегодня к 9 утра. Для real-time: события не должны опаздывать больше 1 минуты.
SQL-проверки:
-- Когда последний раз обновлялась таблица
SELECT max(created_at) AS last_event
FROM events;
-- Сколько часов прошло с последнего обновления
SELECT
max(created_at) AS last_event,
date_diff('hour', max(created_at), current_timestamp()) AS hours_stale
FROM events;
-- Алертить, если данные старше 25 часов (для daily pipeline)
SELECT
case when date_diff('hour', max(created_at), current_timestamp()) > 25
then 'STALE!'
else 'OK'
end AS status
FROM events;
Бизнес-влияние: маркетинг видит вчерашние конверсии, но pipeline сломан — реально данные за позавчера. Решения принимаются на старых данных.
5. Uniqueness (уникальность)
Определение: ключевые идентификаторы уникальны, нет дубликатов.
order_id должен быть уникальным. Email клиента обычно тоже (один email — один customer). Если в таблице два раза один order_id — что считать актуальным?
SQL-проверки:
-- Дубликаты order_id
SELECT order_id, count(*) AS cnt
FROM orders
GROUP BY order_id
HAVING count(*) > 1;
-- Просто проверка наличия дубликатов
SELECT
count(*) AS total_rows,
count(DISTINCT order_id) AS unique_orders,
count(*) - count(DISTINCT order_id) AS duplicates
FROM orders;
-- Дубли email в клиентах
SELECT email, count(*) AS dup_count
FROM customers
GROUP BY email
HAVING count(*) > 1
ORDER BY dup_count DESC;
Бизнес-влияние: дубль заказа удваивает revenue в отчёте. Дубль customer’а двоит cohort analysis.
6. Validity (валидность)
Определение: данные соответствуют установленным правилам формата и значений.
Примеры:
amountдолжно быть >= 0.emailдолжен соответствовать regex email.statusдолжен быть из списка['pending', 'paid', 'cancelled', 'refunded'].phone_numberдолжен быть валидным форматом.created_atне должен быть в будущем.
SQL-проверки:
-- Отрицательные amount
SELECT count(*) FROM orders WHERE amount < 0;
-- Будущие даты
SELECT count(*) FROM orders WHERE created_at > current_timestamp();
-- Невалидные статусы
SELECT count(*) FROM orders
WHERE status NOT IN ('pending', 'paid', 'cancelled', 'refunded');
-- Невалидные emails
SELECT count(*) FROM customers
WHERE email NOT LIKE '%@%.%'; -- грубая проверка
-- Длина номера телефона
SELECT count(*) FROM customers
WHERE length(phone) < 7 OR length(phone) > 15;
Бизнес-влияние: при попытке обработать невалидные данные downstream-pipeline падают. ML-модели обучаются на мусоре и дают плохие прогнозы.
Сводная таблица: что проверять на orders
Приоритизация проверок
Не все измерения одинаково важны для каждой таблицы. На самом деле приоритеты обычно такие:
- Uniqueness — на ключе таблицы. Это must-have, дубликаты ломают всё.
- Completeness — обязательных полей. Без них таблица бесполезна.
- Validity — enum’ы и ranges. Простые проверки, ловят 80% ошибок.
- Consistency — FK-relationships и cross-table. Важно, но дороже проверять.
- Accuracy — самое сложное. Нужны business rules.
- Timeliness — критично для real-time, менее для daily-витрин.
Начинай с uniqueness + completeness. Это 2 теста на каждую таблицу, которые ловят больше всего инцидентов. Уже на 80% накроют типичные проблемы. Постепенно добавляй остальные.
Reality check: data quality не достижим на 100%
Часто junior DE думает, что цель — 100% качество. Это миф. Реальность:
- В источниках всегда есть мусор (опечатки, тестовые записи, баги в продукте).
- Полнота “под 100%” стоит дорого: каждое 9-ка после запятой удваивает усилия.
- Бизнес обычно ОК с 95-99% качеством, если знает про оставшиеся проценты.
Цель — знать, какое качество у твоих данных, и явно его принять. Если accuracy 98% — это нормально для большинства задач. Если 50% — катастрофа.
SLA на data quality — это полезный термин. Например: “completeness на customer_id не меньше 99.5%; uniqueness на order_id = 100%; freshness не больше 25h для daily pipeline”.
Кто отвечает за data quality
В разных компаниях по-разному:
- Data Engineer — отвечает за пайплайн, ловит “поломки в пути”.
- Data Steward — бизнес-роль, владеет определением полей, говорит “что значит accuracy”.
- Source-system owner — продукт-команда, генерирующая данные. Часто причина проблем — у них.
- Analytics Engineer — пишет dbt-тесты, ловит ошибки в трансформациях.
Лучше всего работает культура ownership: у каждой таблицы есть владелец, ответственный за её качество.
Попробуй сам
Возьми любую таблицу в твоей БД (или sample dataset). Напиши SQL-проверки на каждое из шести измерений:
- Completeness: подсчитай %NULL для каждой колонки.
- Uniqueness: найди дубликаты по предполагаемому ключу.
- Validity: найди значения вне диапазона (отрицательные, в будущем, не из enum’а).
- Consistency: проверь FK-ссылки на orphan-записи.
- Timeliness: посмотри
max(updated_at), есть ли отставание. - Accuracy: найди тестовые записи, аномальные значения.
Запиши результаты. Это даст реальную картину твоих данных и понимание, какие тесты должны быть в dbt или Great Expectations.