Сначала спросите, для чего набор будет использован
Один файл может быть достаточен для ориентировочного обзора и опасен для автоматической выплаты. Качество не существует без задачи и последствий. Запишите решение или действие, которое зависит от набора, пользователя результата, срок, допустимые ограничения и худший эффект ошибки. Это определит обязательные поля и severity проверок.
Разделите пригодность и удобство. Красивые названия колонок не компенсируют пропущенный период; единый формат даты не доказывает правильную дату; отсутствие null не гарантирует, что значение относится к нужному объекту. Проверки должны находить нарушение конкретного ожидания, а не создавать общий зелёный балл.
Определите grain, ключ, охват и время
Grain отвечает, что представляет одна строка: пользователя, заказ, событие, позицию заказа или снимок объекта на дату. Без него невозможно решить, что является дублем. Две одинаковые покупки могут быть разными событиями, а две строки с разным временем — обновлениями одного объекта. Запишите grain одним предложением до запуска функции удаления повторов.
Ключ идентифицирует строку на выбранном grain. Он может состоять из нескольких полей, но каждое должно иметь предметный смысл. Суррогатный row_number делает строки различимыми технически, но не обнаруживает дубль объекта. Проверьте null, устойчивость во времени, область уникальности и связь с системой-источником.
Охват описывает ожидаемую популяцию: какие статусы, каналы, регионы или категории входят и исключаются. Время включает event period, timezone, cutoff выгрузки и допустимую задержку. Не смешивайте «последнее обновление файла» и «последнее событие внутри»: свежий файл способен содержать старые данные.
Сохраните неизменяемую исходную копию
Перед исправлениями сохраните raw snapshot в контролируемом хранилище. Зафиксируйте безопасное имя, checksum, размер, число строк и колонок, время получения, источник, способ выгрузки и владельца. Ограничьте доступ и срок хранения по чувствительности данных. Пароль, токен и персональные данные не помещайте в отчёт качества.
Работайте с копией или производной таблицей. Каждое преобразование должно быть повторяемым: запрос, скрипт, шаги инструмента или журнал ручной правки. Если исходник изменился, создайте новую версию, а не перезаписывайте доказательство. Это позволяет отличить дефект источника от ошибки очистки и восстановить расчёт.
Постройте профиль без преждевременных выводов
Профиль — нейтральная карта набора. Посчитайте строки и поля, inferred и ожидаемые типы, число null и пустых строк, distinct count, минимумы и максимумы, длины текста, распределения категорий и границы времени. Для чувствительных значений сохраняйте агрегаты и безопасные примеры, а не копируйте полные записи в отчёт.
Сравните профиль с предыдущей сопоставимой версией. Резкое изменение числа строк или доли категории — сигнал, но не автоматическая ошибка: мог измениться процесс. Поэтому anomaly должна вести к вопросу владельцу и проверке источника. Не «исправляйте» реальное изменение только потому, что оно необычно.
Чек-лист полноты, уникальности и актуальности
Эти три измерения образуют быстрый gate, но работают только вместе с grain и ожиданием. Для каждого теста сохраните выражение, фактический результат, порог, severity, sample нарушений, владельца и disposition. Порог не берут из статьи: его задают по цене ошибки и наблюдаемому процессу.
Проверка | Assertion | Evidence | Когда блокировать | Следующее действие |
|---|---|---|---|---|
Полнота обязательных полей | Ключ, время и поля решения не пусты | Количество и доля пропусков по полю | Нельзя идентифицировать объект или выполнить правило | Карантин; исправить источник или подтвердить восстановление |
Полнота охвата | Есть ожидаемые периоды, категории и источники | Матрица ожидаемого и фактического покрытия | Отсутствует часть популяции, влияющая на вывод | Повторить выгрузку или явно сузить вывод |
Уникальность ключа | Один ключ соответствует одной строке выбранного grain | Группы дублей с count и происхождением | Дубль меняет итог или создаёт повторное действие | Определить каноническую запись по предметному правилу |
Актуальность загрузки | Источник обновлён не позже согласованного cutoff | loaded_at и возраст относительно проверки | Данные старше окна решения | Остановить использование и восстановить загрузку |
Актуальность событий | В наборе есть события до ожидаемой границы | max event_time, задержка и поздние события | Не покрыто требуемое окно или задержка неизвестна | Дождаться закрытия либо пометить предварительный статус |
Проверьте схему и допустимость
Сверьте названия, типы, обязательность и структуру с data contract. CSV не хранит строгие типы, поэтому «00123» легко превратить в 123 и потерять ведущие нули; дата 03/04 неоднозначна; десятичный разделитель зависит от локали. Определите encoding, delimiter, timezone, единицы и правила trim до чтения.
Проверка accepted values полезна для статусов и категорий, но список должен иметь владельца и версию. Новое значение может быть ошибкой или легитимным изменением. Не заменяйте его автоматически на «другое» до выяснения: так исчезает сигнал изменения контракта. Числовые диапазоны проверяйте предметно, а не по историческому минимуму.
JSON Schema помогает проверить форму JSON и обязательные свойства, однако бизнес-правила живут выше. Синтаксически верная валюта может не поддерживаться операцией; дата окончания может быть раньше начала; сумма позиций может не совпасть с итогом. Добавьте cross-field assertions и явные причины отказа.
Проверьте связи и согласованность
Referential integrity отвечает, существует ли ключ из дочерней таблицы в справочнике или родительском наборе. Найдите orphan records, но учитывайте время: событие могло прийти раньше справочника. Разделите ожидаемую задержку и настоящий дефект. Соединение INNER JOIN способно молча удалить orphan и создать красивый, но неполный отчёт.
Согласованность проверяет одинаковый смысл между полями и источниками. Статус «закрыт» должен сочетаться с допустимым временем закрытия; валюта суммы — совпадать с валютой расчёта; локальный и внешний ID — иметь однозначное соответствие. Если системы расходятся, заранее назначьте system of record и процедуру разрешения.
Класс | Пример assertion | Опасная ложная коррекция |
|---|---|---|
Referential | Каждый order.customer_id существует в версии customers | Удалить заказ, потому что справочник задержался |
Cross-field | closed_at заполнен только для закрытого статуса | Подставить текущую дату без доказательства |
Domain | Currency входит в версию поддерживаемого списка | Заменить неизвестную валюту на наиболее частую |
Temporal | start_at не позже end_at в одной timezone | Поменять даты местами автоматически |
Reconciliation | Число уникальных ключей и контрольная сумма сходятся | Подогнать итог ручной строкой |
Сверьте итог с независимым контролем
Reconciliation сравнивает этапы и источники. Сверьте число уникальных ключей до и после преобразования, количество по статусам, суммы в согласованной единице и набор отсутствующих ID. Один общий total недостаточен: потеря одной записи и дубль другой могут взаимно скрыться. Храните разницу и конкретные группы нарушений.
Контроль должен быть независимым от проверяемой формулы. Если отчёт и сверка используют один ошибочный join, оба покажут одинаковый результат. По возможности сравните с системным счётчиком, отдельным export endpoint или сохранённым реестром событий. Объяснимое расхождение документируется вместе с периодом, владельцем и решением.
Не превращайте outlier в ошибку без исследования
Экстремальное значение может быть опечаткой, сменой единицы, редким реальным случаем или изменением процесса. Сначала проверьте исходную запись, соседние поля, историю объекта и owner. Winsorization, удаление или заполнение средним меняют распределение и вывод; такие операции требуют обоснования, версии и сравнения до/после.
Ищите также структурные сдвиги: исчезновение категории, скачок null после релиза, изменение длины строки, новый паттерн задержки. Укажите reference window и сезонность; прошлый месяц не всегда сопоставим. Аномалия является сигналом проверки, а не доказательством плохого качества.
Классифицируйте дефекты по последствиям
Задайте уровни severity до просмотра результатов. Critical блокирует использование, потому что способен вызвать неверное высокозначимое действие или необратимо исказить итог. Error блокирует затронутый сегмент. Warning допускает использование с явным ограничением. Info фиксирует наблюдение. Порог и владелец относятся к конкретному assertion.
Карантин хранит проблемные записи отдельно с причиной, версией правила и ссылкой на исходник. Он не должен становиться вечной свалкой. Для каждой группы назначьте владельца, срок, допустимое действие и способ возврата после исправления. Никогда не направляйте запись из карантина в автоматическое исполнение только ради закрытия очереди.
Автоматизируйте проверки, а не исправления вслепую
Повторяемые assertions должны возвращать нарушающие строки или агрегированное доказательство. Базовый набор включает not-null, unique, accepted values, relationships, freshness и предметные тесты. Запускайте его на источнике и после преобразования. Сохраняйте результат рядом с hash версии данных и кода проверки.
Автоисправление допускается только для детерминированного, подтверждённого правила: например, нормализация заранее согласованного регистра категории. Даже тогда храните исходное значение и счётчик изменений. Догадки — заполнение неизвестной даты, выбор наиболее частого статуса, объединение похожих имён — должны уходить человеку или оставаться missing.
Соберите короткий QA-отчёт
Отчёт начинается с решения: PASS, PASS WITH LIMITATIONS или BLOCKED по заранее утверждённым правилам. Затем указывает dataset ID, checksum, источник, период, cutoff, grain, key, строки и колонки. Таблица tests содержит assertion, severity, результат, число нарушений, ссылку на безопасный sample, владельца и disposition.
В конце перечислите выполненные преобразования, нерешённые ограничения, следующий review и provenance: raw entity, activity обработки, agent или роль. Не прячьте предупреждение в приложении. Пользователь отчёта должен видеть рядом с метрикой, что часть периода предварительная или сегмент исключён.
Иллюстративный пример: выгрузка заказов
Представим синтетический CSV, где одна строка должна соответствовать одному заказу на cutoff. Сначала сохраняется raw checksum, затем проверяются order_id, customer_id, created_at, status, amount и currency. Два одинаковых order_id блокируют автоматическое действие, но не удаляются: владелец выясняет, это повтор выгрузки, версия или ошибка источника.
Далее проверяются пропуски обязательных полей, список статусов, временные границы, customer relationships и согласование суммы с позициями. max created_at сравнивается с ожидаемым cutoff, а количество уникальных заказов — с независимым счётчиком источника. Только после закрытия critical defects формируется производный набор и QA-report.
Практический следующий шаг
Возьмите последнюю выгрузку, но не открывайте её для ручной правки. Создайте raw snapshot и карточку назначения. Запишите grain и кандидатный ключ, затем выполните пять gate-проверок: обязательные null, дубли ключа, ожидаемый охват периода, max event time и одну независимую сверку. Для каждого нарушения назначьте severity и владельца. Если ключ или cutoff нельзя определить, остановите использование и запросите контракт источника.
Назначение, последствия ошибки и пользователь результата названы.
Grain, ключ, охват, период, timezone и cutoff определены.
Raw snapshot сохранён с checksum и ограниченным доступом.
Профиль построен до очистки и сравним с прошлой версией.
Полнота, уникальность и актуальность имеют assertions и evidence.
Schema, accepted values, cross-field и relationships проверены.
Итоги сверены независимым контролем по ключам и агрегатам.
Дефекты классифицированы, помещены в карантин и имеют владельца.
Преобразования воспроизводимы; догадки не выдаются за исправления.
QA-report хранится вместе с версией данных и provenance.
Обсуждение
Комментарии
Обсуждение загрузится при приближении к разделу.