Загрузка истории: CSV, Amplitude, ClickHouse
Перенос накопленной истории событий в ActionPulse — требования к CSV, экспорт Amplitude, чтение из своего ClickHouse, состояния задачи и защита от дублей.
На этой странице
Загрузка нужна один раз — когда вы подключили ActionPulse, а история продукта
осталась в старой системе. Обычный приём событий для этого не подходит: он
рассчитан на поток «здесь и сейчас» и время далеко в прошлом заменяет временем
приёма. Загрузка — отдельный путь, который сохраняет исходное event_time
каждой строки.
Экран — Данные и сбор → Загрузка данных, кнопка «Загрузить данные».
Три источника
| Источник | Что вы даёте | Настройка колонок | Границы одной задачи |
|---|---|---|---|
| CSV-файл | файл до 512 МиБ | вручную, в мастере | размер загружаемого файла |
| Amplitude export | архив gzip JSON Lines до 512 МиБ | фиксирована форматом Amplitude | 5 000 000 строк, 4 ГиБ распакованных данных |
| ClickHouse DSN | строка подключения и SELECT |
вручную, по именам колонок результата | 5 000 000 строк, 256 колонок, 15 минут |
Мастер для CSV состоит из трёх шагов (тип → превью и маппинг → сводка), для
Amplitude и ClickHouse — из двух. Задачи выполняются последовательно одна за
другой, поэтому крупный перенос лучше разбить на несколько файлов или несколько
детерминированных SELECT, а не ждать одну гигантскую задачу.
Требования к файлу CSV
- Кодировка — UTF-8. Файл не перекодируется; текст в другой кодировке превратится в мусор в именах событий и свойств.
- Разделитель — запятая. Кавычки экранируются удвоением (
""), переводы строк — LF или CRLF. - Первая строка — заголовок с именами колонок. Именно по этим именам строится маппинг.
- Размер — до 512 МиБ на запрос.
Превью в браузере читает первые 256 КБ файла и показывает 20 строк, чтобы вы проверили разбор до отправки. Если заголовок не распознан, мастер скажет об этом сразу и не даст перейти дальше.
Сопоставление колонок с полями события
Каждой колонке назначается одна роль:
| Роль | Поле события | Обязательность |
|---|---|---|
Событие (event_name) |
имя события | ровно одна колонка |
Время (time) |
event_time |
ровно одна колонка |
user_id |
известный идентификатор | нужна хотя бы одна из двух |
anon_id |
анонимный идентификатор | нужна хотя бы одна из двух |
Свойство (prop) |
ключ в props |
не обязательно |
| Пропустить | колонка не переносится | — |
Мастер не даёт запустить загрузку, пока event_name или time не назначены
или назначены сразу нескольким колонкам. Колонок-свойств — до 64
(столько же свойств принимает одно событие), имена свойств не должны
повторяться. Имя свойства по умолчанию совпадает с именем колонки, но его
можно переопределить.
Ограничения полей — те же, что у обычного приёма: имя события по правилу
^[a-z0-9_.]{1,128}$, идентификатор до 256 символов, ключ
свойства до 64 символов, значение до 8 КБ. Полный
состав события — в схеме событий.
Значения свойств из CSV и из ClickHouse записываются строками, даже если в источнике это число. Свойства из экспорта Amplitude переносятся как есть, с исходными типами. Если по свойству нужно считать суммы, заранее решите, из какого источника грузить и как потом приводить тип в запросах.
Время события
Формат времени выбирается один на всю задачу:
| Формат | Пример значения |
|---|---|
| ISO 8601 | 2026-07-01T10:15:00Z |
| Unix, секунды | 1782000900 |
| Unix, миллисекунды | 1782000900000 |
YYYY-MM-DD HH:mm:ss |
2026-07-01 10:15:00 |
Часовой пояс из мастера (по умолчанию — часовой пояс проекта) применяется
только к формату YYYY-MM-DD HH:mm:ss: у Unix-времени смысла нет, а значение
ISO 8601 обязано нести собственное смещение — Z или +03:00. ISO-значение
без смещения отклоняется.
Загрузка истории намеренно строже обычного приёма и никогда не подставляет серверное время вместо непонятного:
| Причина отклонения строки | Что означает |
|---|---|
missing_time |
колонка времени пустая |
invalid_time |
значение не разбирается выбранным форматом |
future_time |
время больше чем на 48 ч в будущем |
time_too_old |
время старше срока хранения событий вашего тарифа |
Отсюда прямое следствие: глубина загружаемой истории равна сроку хранения тарифа — от 6 месяцев до 25 месяцев в зависимости от плана, см. тарифы и лимиты. Строки старше этой границы не «дожидаются своего срока», а отклоняются сразу. Загрузить архив десятилетней давности не получится ни на одном тарифе.
Экспорт Amplitude
Единственное поле мастера — файл .jsonl.gz или .gz. Маппинг не
настраивается, он задан форматом Amplitude: event_type → имя события,
user_id и device_id → идентификаторы, time (Unix, миллисекунды) → время
события, event_properties → свойства. Строка без имени события или без обоих
идентификаторов отклоняется.
Идентификатор события берётся из самого экспорта — uuid, $insert_id,
insert_id или event_id, в этом порядке; если ни одного нет, он выводится из
содержимого строки. Границы одной задачи: 5 000 000 строк источника и 4 ГиБ
распакованных данных. Крупный экспорт нужно разбить на несколько файлов и
загрузить несколькими задачами.
Чтение из вашего ClickHouse
Понадобится строка подключения вида clickhouse://user:pass@host:9000/db и
SELECT, возвращающий по строке на событие. Дальше указываются имена колонок
результата: событие, необязательный event_id, user_id, anon_id, время и
список колонок-свойств через запятую. Кнопка «Начать загрузку» становится
активной, когда заданы DSN, запрос, колонка события, колонка времени и хотя бы
один из идентификаторов.
Прогресс такой задачи держится на 50 %, пока она идёт: общее число строк
заранее неизвестно, а спрашивать count() у вашего сервера продукт не
пытается. Задача останавливается через 15 минут — это защита от бесконечного
SELECT, который иначе заблокировал бы очередь. Долгий перенос разбивайте на
детерминированные запросы по диапазонам.
Состояния задачи
Карточка задачи обновляется сама, пока задача не завершится.
| Статус | Что происходит | Что делать |
|---|---|---|
| В очереди | задача принята, воркер её ещё не взял | можно отменить |
| Выполняется | строки читаются и принимаются | следите за счётчиками, можно отменить |
| Отменяется | отмена запрошена | подождите: воркер остановится после ближайшего безопасного чекпоинта |
| Отменён | задача остановлена вами | для CSV доступна кнопка «Продолжить загрузку» |
| Готово | источник прочитан до конца | сверьте «Принято» и «Отклонено» |
| Ошибка | задача упала | текст ошибки — на карточке |
Счётчики на карточке — «Принято» и «Отклонено». Отдельного счётчика дублей задача не ведёт: подавленные повторы попадают в «Принято», а совпадений с уже загруженной ранее историей продукт не ищет вовсе.
Типичные причины статуса «Ошибка»: источник ClickHouse не отвечает или запрос к нему упал, превышена граница 5 000 000 строк, архив Amplitude распаковался больше чем в 4 ГиБ, задача ClickHouse не уложилась в 15 минут. Эти отказы касаются задачи целиком — уже принятые строки остаются в проекте.
Отмена и продолжение
Отменить можно задачу в статусе «В очереди» или «Выполняется». Отмена идемпотентна: повторное нажатие ничего не ломает. Воркер не обрывается посередине батча — он доводит текущий безопасный чекпоинт и только потом останавливается, поэтому статус какое-то время держится на «Отменяется».
Продолжить можно только CSV и только из статуса «Отменён»: кнопка «Продолжить загрузку» возобновляет чтение с последнего сохранённого чекпоинта, а карточка показывает, сколько строк уже надёжно принято. Для Amplitude и ClickHouse продолжения нет — создайте задачу заново.
Повторная загрузка и дубли
Продолжение отменённой CSV-задачи дублей не создаёт: чтение возобновляется с сохранённого чекпоинта, а строки из окна между чекпоинтом и остановкой получают те же идентификаторы событий, поэтому повторно не записываются.
А вот новая задача по тому же файлу создаёт вторую копию событий. Ключа идемпотентности на уровне файла или задачи нет, и продукт не сравнивает содержимое новой загрузки с уже принятой историей. Отсюда рабочий порядок:
- Проверьте маленький срез.
- Загрузите полный файл одной задачей.
- Если задача упала на середине — не запускайте её заново «на всякий случай». Сначала посмотрите в отчётах или в SQL-консоли, что уже попало в проект, и грузите только недостающий диапазон.
Своя колонка идентификатора события есть только у загрузки из ClickHouse; в
маппинге CSV такой роли нет. Но и указанный event_id не спасает от повторной
загрузки: защита от дублей действует внутри задачи, а не между задачами.
Перед загрузкой
- Убедитесь, что
user_idв истории тот же, что вы отправляете сейчас. Иначе один человек разделится на двух, и удержание посчитается неверно. - Приведите имена событий к
^[a-z0-9_.]{1,128}$заранее, особенно для CSV. - Не кладите персональные данные в свойства — приём вырезает то, что распознал как персональные данные и как секрет, но полагаться на это как на политику нельзя. См. приватность.
- Помните про порядок: события, загруженные историей, получают ваше
event_time, но время приёма у них — момент загрузки. Выгрузки событий фильтруются по времени приёма, см. выгрузки. - После загрузки откройте проверку интеграции и сверьте, что имена событий совпали с теми, что приходят из живого потока.