-- Схема аналитики ClickHouse. -- -- Этот каталог монтируется в контейнер как /docker-entrypoint-initdb.d, -- поэтому скрипт применяется ТОЛЬКО при первой инициализации пустого data-каталога. -- Flyway у нас только для Postgres; изменения схемы здесь — новым файлом -- 00N_*.sql (и применением вручную на существующем контуре) плюс раздел в DEPLOY.md. CREATE DATABASE IF NOT EXISTS analytics; -- Единая широкая таблица событий (см. docs/events.md). -- Партиционирование по дню: сырые партиции удаляются после ежедневного бэкапа -- на домашний сервер (scripts/clickhouse_backup.sh), поэтому удаление должно -- быть дешёвым (DROP PARTITION, без mutation). CREATE TABLE IF NOT EXISTS analytics.events ( event_time DateTime('UTC'), event_type LowCardinality(String), user_id Int64, username String, chat_id Int64, payload String, bot_version String, prod UInt8 ) ENGINE = MergeTree PARTITION BY toYYYYMMDD(event_time) ORDER BY (event_time, event_type, user_id); -- Агрегат: события по дням и типам. Остаётся на VPS, когда сырые удалены. CREATE TABLE IF NOT EXISTS analytics.events_daily ( day Date, event_type LowCardinality(String), user_id Int64, chat_id Int64, events UInt64 ) ENGINE = SummingMergeTree ORDER BY (day, event_type, user_id, chat_id); CREATE MATERIALIZED VIEW IF NOT EXISTS analytics.events_daily_mv TO analytics.events_daily AS SELECT toDate(event_time) AS day, event_type, user_id, chat_id, count() AS events FROM analytics.events GROUP BY day, event_type, user_id, chat_id; -- Агрегат: денежные потоки по дням (сумма amount из payload событий экономики). CREATE TABLE IF NOT EXISTS analytics.money_daily ( day Date, event_type LowCardinality(String), user_id Int64, amount_sum Int64, events UInt64 ) ENGINE = SummingMergeTree ORDER BY (day, event_type, user_id); CREATE MATERIALIZED VIEW IF NOT EXISTS analytics.money_daily_mv TO analytics.money_daily AS SELECT toDate(event_time) AS day, event_type, user_id, sum(JSONExtractInt(payload, 'amount')) AS amount_sum, count() AS events FROM analytics.events WHERE event_type IN ('money_accrual', 'money_spend') GROUP BY day, event_type, user_id;