1. Начните с задачи, а не с базы данных
Представим интернет-магазин. Метрика показывает поведение на сайте, система заказов — оплаты и отмены, рекламные кабинеты — расходы. Команда хочет оценить, какие источники приводят оплаченные заказы с учётом возвратов. Одного отчёта о визитах для этого недостаточно.
Хранилище позволяет собрать таблицы рядом и описать общий расчёт. Оно также пригодится для повторяемого анализа когорт и сохранения истории преобразований.
Если задача решается одним готовым отчётом или разовой выгрузкой, регулярная инфраструктура может оказаться лишней. У неё будут стоимость, обслуживание и ответственный за сбои. Сначала запишите, какое решение вы сможете принимать после её появления.
2. Что делают Logs API, Python и ClickHouse
Это один из возможных вариантов архитектуры. Python не обязателен, но удобен для программы, которая выполняет шаги по расписанию. ClickHouse здесь — выбранное хранилище, а не автоматическое решение всех проблем качества данных.
Logs API предоставляет неагрегированные данные. Текущий день недоступен для выгрузки, а записи о визитах могут уточняться позже. Поэтому вчерашняя успешная загрузка не означает, что данные за вчера больше никогда не изменятся.
Последовательность одного запуска
- Определить счётчик, даты и нужные поля.
- Запросить подготовку выгрузки и сохранить идентификатор запроса.
- Дождаться готовности или зафиксировать ошибку.
- Скачать все части, которые относятся к этому запросу.
- Проверить состав полей, даты, ключи и количество записей.
- Загрузить результат во временную область и проверить его ещё раз.
- Сделать проверенную версию доступной отчётам и записать результат запуска.
Нельзя считать операцию завершённой только потому, что программа скачала первый файл. У запроса может быть несколько частей. После сохранения и проверки файлов предусмотрите очистку подготовленных логов в Метрике, чтобы освобождать квоту.
3. Определите, что означает одна строка
Для таблицы визитов одна строка должна описывать один визит. Для таблицы заказов — один заказ в согласованном состоянии. Для товаров заказа — одну позицию заказа. Эти уровни нельзя незаметно смешивать.
У визита Метрики есть идентификатор, уникальный в пределах года. Если храните несколько лет или счётчиков, одного visitID недостаточно: предусмотрите счётчик и год в ключе. Длинные идентификаторы сохраняйте без потери точности.
Отдельно зафиксируйте часовой пояс, валюту, трактовку отмен и источник выручки. Сумма созданного заказа, сумма оплаты и сумма после возвратов — разные показатели.
Полезно хранить исходную выгрузку отдельно от подготовленных таблиц. Если правило расчёта изменится, можно будет пересобрать результат без догадок о том, что происходило с данными.
4. Повторный запуск не должен удваивать данные
Учебная ситуация: за день получено 18 437 визитов. Загрузка завершилась, но программа не дождалась ответа сервера и решила, что произошёл сбой. При повторной простой вставке может получиться 36 874 строки. Посетителей больше не стало — дважды загрузили одну порцию.
Нужное свойство называется идемпотентностью: повторная обработка той же версии данных даёт тот же итог. Это правило работы загрузчика, которое нужно спроектировать и проверить.
Понятная схема для начала
Соберите полную версию выбранного периода во временной таблице. После проверок замените соответствующий период в рабочем представлении данных согласованным способом. До завершения замены отчёты должны продолжать видеть предыдущую полную версию.
Это описание архитектуры, а не команда «сначала удалить, потом вставить». Если удалить рабочие записи до подготовки замены, сбой оставит отчёт без данных. Конкретный механизм зависит от схемы таблиц и настроек хранилища.
У ClickHouse есть механизмы защиты от повторных вставок, но их действие зависит от движка, настроек и окна дедупликации. Нельзя предполагать, что любые одинаковые строки исчезнут автоматически. Проверяйте повторную загрузку на той конфигурации, которая используется в проекте.
Уточнения источника — отдельный случай
Задайте период повторной выгрузки недавних дней и измеряйте, как долго меняются записи в вашем счётчике. Перезагрузка должна обновлять версию, а не добавлять её к старой. Сохраните возможность отдельно пересчитать более старый период, если обнаружится ошибка.
5. Почему после объединения растёт выручка
В таблице заказов есть заказ A-7319 на 7 843 рубля. В таблице товаров у него три позиции. Если присоединить товары к заказу, сумма заказа окажется в каждой из трёх строк.
| Заказ | Позиция | Сумма всего заказа |
|---|---|---|
| A-7319 | Товар А | 7 843 ₽ |
| A-7319 | Товар Б | 7 843 ₽ |
| A-7319 | Товар В | 7 843 ₽ |
Суммирование последнего столбца даст 23 529 рублей вместо 7 843. Соединение могло выполниться без технических ошибок, но смысл суммы изменился.
Перед объединением определите ожидаемое число соответствий: одна строка к одной или одна к нескольким. Если нужен результат по заказам, сначала приведите нужные сведения о товарах к одной строке на заказ. Если нужен результат по товарам, используйте стоимость позиций с согласованным распределением скидок, доставки и возвратов.
Не исправляйте проблему через SUM(DISTINCT сумма): разные заказы могут иметь одинаковую стоимость. Проверять нужно ключи и уровень детализации.
То же относится к рекламным расходам. Расход за кампанию и день нельзя бездумно присоединить к каждому визиту и затем просуммировать. Сначала приведите обе стороны к сопоставимому уровню.
6. Как понять, что загрузке можно доверять
| Что проверяем | Какую проблему ловим |
|---|---|
| Все ожидаемые части скачаны | Неполная выгрузка |
| Все даты покрыты успешными запросами | Пропущенный день, который приняли за нулевой трафик |
| Ключи заполнены, повторы разобраны | Дубли и записи, которые невозможно корректно связать |
| Повтор запуска не меняет итог той же версии | Удвоение данных после сбоя |
| Суммы и число ключей сверены до и после JOIN | Размножение строк при объединении |
| Видна дата последнего полного обновления | Устаревший отчёт, который выглядит свежим |
Нулевой трафик и отсутствие загрузки — разные состояния. Храните журнал с периодом, идентификатором запуска, статусом, количеством частей и строк, временем завершения и причиной ошибки.
Успешное завершение программы — только одна проверка. Например, она могла загрузить пустой файл вместо ожидаемых записей. Сравнивайте объём с предыдущими периодами, но расследуйте отклонение, а не объявляйте любое снижение технической ошибкой.
При расхождении с интерфейсом Метрики сначала сопоставьте даты, фильтры, определения и обработку данных. Подгонять итоговую сумму под интерфейс случайным коэффициентом нельзя.
7. Что согласовать до регулярного запуска
Кто получает сообщение об ошибке? Сколько времени отчёт может оставаться без обновления? Где хранятся исходные файлы? Как восстановить предыдущую проверенную версию? Эти ответы нужны ещё до того, как отчётом начнут пользоваться ежедневно.
Токены API и пароль базы храните в защищённой конфигурации сервера, а не в публичной странице или открытом репозитории. Доступ к данным выдавайте под конкретные задачи. Проверяйте восстановление, а не только наличие резервной копии.
Начните с одного проверяемого результата
Для первой версии достаточно одного счётчика, понятной таблицы и одного отчёта. Добейтесь полноты, безопасного повторного запуска и воспроизводимого расчёта. Затем добавляйте заказы, рекламу и более сложные исследования.
Ценность хранилища — в возможности объяснить происхождение каждой цифры и пересчитать её по известным правилам.
Перейти к продуктовой аналитике