topfans/backend/migrations/2026_06_08_001_statistic_events.sql
zerosaturation f5ece5e1d2 feat(statistic): T3 service skeleton (config + main + healthz + metrics + 10 SQL)
- 6 config blocks (DB/Redis/Channel/Refresh/Partition/Extension with 4 EnableXxx=false)
- 14 Prometheus metric declarations
- self-impl healthz (/healthz + /metrics) — bypasses pkg/health to keep /metrics
- main.go startup: logger → config → DB → Redis → healthz HTTP :21009
- 10 SQL migrations: events partitioned + 4 MV + 3 pre-agg + refresh_log + 7-day initial

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 17:20:53 +08:00

38 lines
1.3 KiB
SQL

-- statistic 服务 events 原始表
-- 创建时间: 2026-06-08
-- 说明: 事件原始表,按 received_at 按日分区
-- 关联: spec §3.2
-- 1. 创建 schema
CREATE SCHEMA IF NOT EXISTS statistic;
-- 2. 创建 events 主表(按 received_at 按日分区)
CREATE TABLE IF NOT EXISTS statistic.events (
id BIGSERIAL,
event_id UUID NOT NULL,
user_id BIGINT NOT NULL,
star_id BIGINT NOT NULL,
event_type VARCHAR(64) NOT NULL,
occurred_at TIMESTAMPTZ NOT NULL,
received_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
properties JSONB NOT NULL DEFAULT '{}',
PRIMARY KEY (id, received_at)
) PARTITION BY RANGE (received_at);
-- 3. 唯一约束(去重):同一 event_id 不能重复
CREATE UNIQUE INDEX IF NOT EXISTS idx_events_event_id
ON statistic.events (event_id, received_at);
-- 4. 看板查询主索引(覆盖 90% 查询)
CREATE INDEX IF NOT EXISTS idx_events_user_star_type_time
ON statistic.events (user_id, star_id, event_type, received_at DESC);
-- 5. 趋势分析索引
CREATE INDEX IF NOT EXISTS idx_events_star_type_time
ON statistic.events (star_id, event_type, received_at DESC);
-- 6. JSONB 属性 GIN 索引
CREATE INDEX IF NOT EXISTS idx_events_properties_gin
ON statistic.events USING GIN (properties);