— «Работай из любой точки России!» — кричали HR-офферы.
— «У нас облачный BI, всё летает!» — вторили тимлиды.
А потом ты выезжаешь за МКАД, садишься в поезд или просто решаешь поработать с веранды на даче, и реальность бьет под дых. Мобильный интернет сегодня — это лотерея. Вчера он был, сегодня его «прикрутили» из-за учений, завтра ты въехал в «белое пятно», а послезавтра твой VPN забанили вместе с протоколом.
И вот ты сидишь, смотришь на крутящийся спиннер в браузере и понимаешь: твоя хваленая облачная IDE превратилась в дорогой скринсейвер. Весь твой BI-стек остался где-то там, за горизонтом событий, куда пакеты не долетают. Схема замерла, ETL превратился в тыкву, а изменения, которые ты вырисовывал последние полчаса, отправились в цифровую вальгаллу.
В этой статье я покажу, как в системе asapBI реализована честная оффлайн работа на примере графического SQL запроса к Clickhouse. Расскажу о том, как под капотом подружились локальное хранилище и тяжелые графы, и почему фраза «интернета нет, но вы моделируйте» — это теперь не издевка, а реальный фича-реквест.

Работа в оффлайне с локальным стеком — это не просто «чтобы работало в лесу». Это принципиально другой уровень контроля над процессом:
Твои данные — твоя крепость (Никто не сотрет)
В общей dev-базе всегда есть риск, что коллега Вася решит «почистить место» или накатит кривой миграционный скрипт, который снесет твою тестовую таблицу с идеально подобранными кейсами.
Плюс: В локальном Docker ты сам себе админ. Твои данные живут в томах (volumes), и никто, кроме тебя, их не тронет. Хочешь — храни их годами, хочешь — делай бэкап одной папкой.
Эксперименты без «расстрела»
Попытка выполнить тяжелый JOIN или сложную View на общем сервере может высадить CPU в 100% и парализовать работу всей команды.
Плюс: В оффлайне ты можешь «жарить» свой процессор как угодно. Если запрос ушел в бесконечный цикл или съел всю память — упадет только твой контейнер, а не кластер.
Версионность и "Time Machine" через Git
Когда логика запроса хранится в базе (как обычная View), трудно отследить, кто и когда её поменял.
Плюс: Твой View — это JSON-файл. Ты можешь создать ветку feature/new-logic, наворотить там схем, а потом сделать diff и посмотреть, что именно изменилось в графе. Это настоящий Code Review для аналитики.
Мы работаем с «цифровым двойником» структуры БД.
Плюс: Можно крутить связи, менять типы данных и перестраивать логику, не нагружая общий сервер бесконечными ALTER или проверочными SELECT. А если вариант разработки не получился – просто создать среду заново.
Итак, что же в asapBI можно из BI-работ делать оффлайн? Все. Да-да, и «даже на парковке» 😉
Не теряйте время, для оффлайн-работы надо сначала подготовиться. Это мы сделаем за 3 шага:
1. Подключение к корпоративному Git и скачивание проекта в локальную папку.
Удобно делить проекты по направлениям: вот это финансы, это – сбыт. На уровне asapBI такой проект видится в виде папки:

2. Установка BI-стека
В проекте присутствует файл docker-compose.yml. Этот файл вместе с установленным докером запускает локально нужный нам BI-стек. Обычно этот файл делают админы и кладут в git, но при желании мы сами можем его поправить – например, добавить Airflow.
Пример файла docker-compose.yml для локального запуска PostgreSQL и Clickhouse:
Скрытый текст
services: asapbi-postgres: image: postgres:15-alpine container_name: asapbi-postgres restart: unless-stopped environment: POSTGRES_USER: admin POSTGRES_PASSWORD: admin POSTGRES_DB: demo PGDATA: /var/lib/postgresql/data/pgdata ports: - "15432:5432" volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U admin -d demo"] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - asapbi-net asapbi-clickhouse: image: clickhouse/clickhouse-server:24.8-alpine container_name: asapbi-clickhouse restart: unless-stopped environment: CLICKHOUSE_USER: admin CLICKHOUSE_PASSWORD: admin CLICKHOUSE_DB: analytics ports: - "18123:8123" # HTTP - "19000:9000" # Native volumes: - clickhouse-data:/var/lib/clickhouse - clickhouse-logs:/var/log/clickhouse-server healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 30s networks: - asapbi-net volumes: postgres-data: driver: local clickhouse-data: driver: local clickhouse-logs: driver: local networks: asapbi-net: driver: bridge
Предварительно нужно скачать и установить Docker Desktop.
Теперь запуск и остановка локальных баз данных осуществляется из интерфейса asapBI (при первом старте докер их самостоятельно скачает и установит):

Конечно, старт/стоп можно делать и через консоль, а также через сам Docker Desktop.
3. Наполнение баз данных
Итак, базы данных у нас уже запущены. Надо подумать про наполнение – создание таблиц, загрузку данных.
Здесь можно поступить по-разному. Например, взять DBeaver, создать в базах таблицы и наколотить туда данных.
Второй вариант – в скачанном git-проекте могут быть файлы с расширением *.dbcopy-json. Этот файл содержит правила копирования:
Скрытый текст
{ "description": "Копирование клиентов с подготовкой и очисткой", "beforeSQL": [ "BEGIN;", "SET session_replication_role = replica;", "CREATE TEMP TABLE IF NOT EXISTS _copy_log (ts timestamptz, msg text);" ], "afterSQL": [ "SET session_replication_role = DEFAULT;", "INSERT INTO _copy_log VALUES (now(), 'Copy completed');", "COMMIT;" ], "tables": [ { "schema": "reference", "table": "clients", "where": "is_active = true AND created_at >= '2024-01-01'", "beforeSQL": [ "DROP INDEX IF EXISTS idx_clients_region_id", "DELETE FROM reference.clients WHERE created_at >= '2024-01-01'" ], "afterSQL": [ "CREATE INDEX IF NOT EXISTS idx_clients_region_id ON reference.clients (region_id)", "ANALYZE reference.clients" ] }, { "schema": "sales", "table": "orders", "where": "order_date >= '2024-01-01'", "beforeSQL": "ALTER TABLE sales.orders DISABLE TRIGGER ALL", "afterSQL": "ALTER TABLE sales.orders ENABLE TRIGGER ALL" }, { "schema": "analytics", "table": "user_sessions", "where": "", "beforeSQL": null, "afterSQL": null } ] }
Открыв файл и выбрав базу-источник и локальную базу-приемник, можно скопировать себе часть тестовых данных.
Также в этот файл можно поместить SQL, чтобы при старте именно под вашу задачу создавались таблицы и загружались тестовые данные.
Внимание – безопасники будут сильно против копирования данных из продуктива! Поэтому только тестовые данные с сервера разработки, не имеющие к реальному миру никакого отношения.

Графический View
А теперь, выбрав запущенный ранее локальный Clickhouse (или другую базу данных), можно строить графические View:

Графический View – это тоже json-файл. Это значит версионность, Code Review и легкий откат.
Если строить SQL-выборки непосредственно в BI-системах - бизнес-логика зашивается на уровне конкретного дашборда. В одном дашборде площадь посчитали одним образом, в другом - другим, а истина вообще где-то рядом. Единой точки правды не получается, и Заказчик удивленно показывает разные цифры в разных дашбордах для одного и того же показателя.
Если писать SQL-выборки на уровне дашборда, то не происходит накопления знаний и фиксации алгоритмов. Вынос алгоритмов из дашборда на уровень View помогает накапливать знания и дает единую точку правды для разных дашбордов при переиспользовании View.
Существует вообще мнение, что алгоритмы расчетов следует фиксировать еще раньше, перед витринами:

Документирование разработок
Сразу после сохранения документация начинает устаревать – точно так же, как автомобиль, выехавший из салона, тут же теряет часть своей стоимости. Чем дальше, тем больше разъезжается документация и реальные настройки.
А что, если при изменении модели не надо никуда далеко ходить, а править тут же, рядом с объектом? Для этого, например, в той же папке с графической View есть файлы с таким же именем, но с другим расширением - они отображаются под узлом View:

Можно добавлять, создавать любые файлы, которые может открывать VSCode:


При изменении объекта разработчику ничего не стоит тут же открыть документацию и прокомментировать изменения.
Эти все файлы – в текстовом формате, а это значит, что их можно скормить как AI, так и автоматическому сборщику документации.
Таким образом у нас всегда будет актуальная документация на проекте, и пусть под массой стопки бумаг содрогнется стол, когда на него будет положена проектная распечатка 😉
Песочница
Что же у нас получилось? А получилась личная песочница, в которой можно исследовать гипотезы, ошибаться, ронять сервер - и ничего за это не будет.
Можно даже запускать на ночь AI, если наураганит чушь - можно откатить разработку на начало.
Ну а если все хорошо - синхронизировать изменения с общим Git и общими серверами разработки.
🎯 Итог: оффлайн-работа в asapBI — это не просто «работа без интернета». Это полноценная локальная среда разработки с версионностью, изоляцией, безопасностью экспериментов и актуальной документацией. Теперь фраза «работай из любой точки» обретает новый смысл — даже если этой точкой является крыша поезда или палатка на море.
