asapBI: работа с базами данных в оффлайне, или «Эй, обалдел!??? У тебя и так удаленка!!!»
— «Работай из любой точки России!» — кричали 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 шага
Не теряйте время, для оффлайн-работы надо сначала подготовиться. Это мы сделаем за 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 есть файлы с таким же именем, но с другим расширением - они отображаются под узлом View:
Можно добавлять, создавать любые файлы, которые может открывать VSCode:
При изменении объекта разработчику ничего не стоит тут же открыть документацию и прокомментировать изменения.
Эти все файлы – в текстовом формате, а это значит, что их можно скормить как AI, так и автоматическому сборщику документации.
Таким образом у нас всегда будет актуальная документация на проекте, и пусть под массой стопки бумаг содрогнется стол, когда на него будет положена проектная распечатка 😉
Песочница
Что же у нас по итогу получилось? А получилась личная песочница, в которой можно исследовать гипотезы, ошибаться, ронять сервер - и ничего за это не будет.
Можно даже запускать на ночь AI, если наураганит чушь - можно откатить разработку на начало.
Ну а если все хорошо - синхронизировать изменения с общим Git и общими серверами разработки.