# 埋点与统计表结构说明 > 本文档说明平台埋点统计系统的 **表结构、分层关系、数据流向、关联键与查询口径**。 > 与 [`前端埋点接入指南.md`](./前端埋点接入指南.md)(接入 API)配合使用。 **文档版本**:v1.0 **最后更新**:2026-06-17 **DDL 来源**:`alien-entity/src/main/resources/db/migration/analytics_schema.sql`(新环境) **旧环境升级**:`analytics_tables_dashboard_upgrade.sql` --- ## 一、设计目标 | 目标 | 实现方式 | |------|----------| | 原始行为可追溯 | 所有 scene 落 `analytics_event` 流水 | | 看板查询快 | 按自然日预聚合到 `analytics_daily_summary` | | 明细分页/下钻 | 用户/商家/内容等 `*_stat` 明细表 | | 当日准实时 | 埋点同步写 `*_today`,每小时跑批覆盖 | | 历史可查 | 零点归档到 `*_history`,保留 30 天 | **核心原则**:数据库层 **不设外键**;表之间通过 `user_id`、`merchant_id`、`content_type + content_id`、`stat_date`、`event_code` 等字段 **逻辑关联**。 --- ## 二、表清单总览 共 **4 张基础表 + 12 张明细表(6 组 today/history)**。 ### 2.1 基础表(不参与 today/history 拆分) | 表名 | Java 实体 | 粒度 | 说明 | |------|-----------|------|------| | `analytics_event` | `AnalyticsEvent` | 每条埋点事件 | **原始日志**,所有统计的源头 | | `analytics_ai_request` | `AnalyticsAiRequest` | 每次 AI API 调用 | 响应耗时,不写 event 表 | | `analytics_daily_summary` | `AnalyticsDailySummary` | 每天 1 行 | 四页看板 KPI 宽表 | | `analytics_stat_job_log` | `AnalyticsStatJobLog` | 每次跑批任务 | 运维排查用 | ### 2.2 明细表(today + history 成对) | 今日表 | 历史表 | Java 实体(today / history) | 唯一键 | |--------|--------|------------------------------|--------| | `analytics_user_stat_today` | `analytics_user_stat_history` | `AnalyticsUserStatToday` / `AnalyticsUserStat` | `user_id` / `(stat_date, user_id)` | | `analytics_merchant_stat_today` | `analytics_merchant_stat_history` | `AnalyticsMerchantStatToday` / `AnalyticsMerchantStat` | `merchant_id` / `(stat_date, merchant_id)` | | `analytics_content_stat_today` | `analytics_content_stat_history` | `AnalyticsContentStat` / `AnalyticsContentStatHistory` | `(content_type, content_id)` / `(stat_date, content_type, content_id)` | | `analytics_category_daily_today` | `analytics_category_daily_history` | `AnalyticsCategoryDailyToday` / `AnalyticsCategoryDaily` | `business_category` / `(stat_date, business_category)` | | `analytics_ai_chat_stat_today` | `analytics_ai_chat_stat_history` | `AnalyticsAiChatStat` / `AnalyticsAiChatStatHistory` | `chat_id` / `(stat_date, chat_id)` | | `analytics_report_record_today` | `analytics_report_record_history` | `AnalyticsReportRecord` / `AnalyticsReportRecordHistory` | `report_id` / `(stat_date, report_id)` | --- ## 三、分层架构 ``` ┌─────────────────────────────────────────────────────────────────┐ │ L0 接入层 POST /analytics/front/* + POST /analytics/detail/* │ └───────────────────────────────┬─────────────────────────────────┘ │ ┌───────────────────────┼───────────────────────┐ ▼ ▼ ▼ ┌───────────────┐ ┌─────────────────┐ ┌──────────────────┐ │ analytics_event│ │ analytics_ai_ │ │ *_today 明细表 │ │ (事件流水) │ │ request │ │ (当日增量/快照) │ └───────┬───────┘ └────────┬────────┘ └────────┬─────────┘ │ │ │ │ POST /analytics/stat/calculate(定时/手动) │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ L2 汇总层 analytics_daily_summary(按 stat_date 一行 KPI) │ │ L1 明细层 *_today 覆盖/补全 + 历史日写入 *_history(补跑时) │ └───────────────────────────────┬─────────────────────────────────┘ │ 零点 analyticsArchiveDaily ▼ *_history(stat_date=昨日,保留 30 天) │ ▼ GET /analytics/*/charts、/summary(报表读层) ``` ### 3.1 三层职责 | 层级 | 表 | 职责 | |------|-----|------| | **L0 原始** | `analytics_event`、`analytics_ai_request` | 保留完整行为流水;支持漏斗下钻、复杂去重、cohort 留存 | | **L1 明细** | `*_stat_*`、`*_daily_*`、`report_record_*` | 按用户/商家/内容/品类/会话/举报预聚合,支撑明细分页与 TOP 榜 | | **L2 汇总** | `analytics_daily_summary` | 按自然日一行,支撑看板 KPI 卡片与趋势图 | --- ## 四、数据生命周期 ### 4.1 实时写入(埋点服务) **入口**:`AnalyticsTrackServiceImpl` **路径**:`POST /analytics/front/report`(及 register/login/logout/heartbeat 等专用接口) 每次成功上报的典型步骤: 1. 将 `scene` 映射为 `event_code`,插入 `analytics_event`(`event_id` 幂等) 2. 按场景 **同步更新** 对应 `*_today` 表(非全部 scene 都会写明细,见下表) | scene / 接口 | event_code | 同步写明细 | |--------------|------------|------------| | `APP_LAUNCH` 等通用 report | `user.launch` 等 | 部分场景仅写 event | | `USER_HEARTBEAT` / heartbeat | `user.heartbeat` | `user_stat_today`(last_active_time、在线时长) | | `APP_REGISTER` / user/register | `user.register` | `user_stat_today` | | `USER_LOGIN` / `USER_LOGOUT` | `user.login` / `user.logout` | `user_stat_today` | | `MERCHANT_VIEW` / merchant/view | `merchant.view` | `merchant_stat_today`(visit_uv/pv) | | `CONTENT_INTERACT` | `content.interact` | `content_stat_today`(互动计数) | | `AUDIT_*` | `audit.*` | `content_stat_today`(审核状态) | | `REPORT_SUBMIT` / `REPORT_HANDLE` | `report.*` | `report_record_today` | | `AI_CHAT_END` | `ai.chat.end` | event + 建议 `/detail/ai-chat` 写 `ai_chat_stat_today` | | `POST /analytics/front/ai-request` | — | 仅 `analytics_ai_request` | | `POST /analytics/detail/*` | 可选 | 直接 upsert 对应 `*_today` | **明细路由**:`AnalyticsDetailStoreServiceImpl` 根据 `statDate` 是否为当天,自动选择写 `*_today` 或 `*_history`。 ### 4.2 定时统计(跑批服务) **入口**:`AnalyticsStatisticsServiceImpl.calculate(statDate, scope, triggerType)` **触发**: | 方式 | 接口 / 任务 | |------|-------------| | 手动 | `POST /analytics/stat/calculate` | | 每小时 | XXL-JOB `analyticsCalculateTodayHourly`(建议 cron: `5 5 * * * ?`) | | 前日完整 | XXL-JOB `analyticsCalculateYesterdayDaily`(`0 0 2 * * ?`) | | 次日留存 | XXL-JOB `analyticsCalculateRetention`(`0 0 3 * * ?`) | **scope 与任务对应**: | scope | 方法 | 输出表 | |-------|------|--------| | `USER` | `calculateUserStat` | `user_stat_*` | | `MERCHANT` | `calculateMerchantStat` | `merchant_stat_*` | | `MERCHANT` | `calculateCategoryDaily` | `category_daily_*` | | `CONTENT` | `calculateContentStat` | `content_stat_*` | | `AI_CHAT` | `calculateAiChatStat` | (明细主要由 detail 接口维护) | | `DAILY` | `calculateDailySummary` | `analytics_daily_summary` | | `ALL` | 以上全部 | — | 跑批 **以 `analytics_event` 为主数据源**,对明细表做 **覆盖/补全**(非简单 +1 累加),再汇总到 `daily_summary`。 ### 4.3 零点归档 **入口**:`AnalyticsArchiveServiceImpl.archiveYesterday()` **任务**:XXL-JOB `analyticsArchiveDaily`(`0 0 0 * * ?`) ``` 1. INSERT *_history ← SELECT * FROM *_today(stat_date = 昨日) 2. DELETE *_history WHERE stat_date < 今天 - 30 天 3. TRUNCATE *_today ``` **不归档的表**: - `analytics_event`(需单独制定清理/分区策略) - `analytics_ai_request` - `analytics_daily_summary`(按 `stat_date` 长期保留) --- ## 五、关联键与实体关系 ### 5.1 核心维度 | 维度 | 字段 | 出现位置 | |------|------|----------| | 用户 | `user_id` | event、user_stat、ai_chat_stat、report_record | | 商家 | `merchant_id` | event、merchant_stat | | 内容 | `content_type` + `content_id`(event 中为 `target_id`) | event、content_stat、report_record | | 自然日 | `stat_date` | history 表 daily_summary | | 经营品类 | `business_category` (1–7) | event、category_daily | | 店铺类型 | `shop_type` (1–3) | event、merchant_stat | | 举报单 | `report_id`(通常 = 提交时 `event_id`) | report_record | ### 5.2 ER 关系(逻辑) ``` analytics_event ├─ user_id ──────────► analytics_user_stat_*.user_id ├─ merchant_id ──────► analytics_merchant_stat_*.merchant_id ├─ content_type + target_id ► analytics_content_stat_*.content_type + content_id ├─ business_category ► analytics_category_daily_*.business_category └─ event_time 按日聚合 ► analytics_daily_summary.stat_date analytics_ai_request.created_time 按日聚合 ► daily_summary.ai_request_count / 响应时长 analytics_report_record ◄── REPORT_SUBMIT/HANDLE(report_id 关联) ``` ### 5.3 today / history 查询约定 报表 Mapper 普遍使用 **UNION ALL**: ```sql -- 历史段 SELECT ... FROM analytics_xxx_stat_history WHERE stat_date >= #{startDate} AND stat_date <= #{endDate} UNION ALL -- 查询区间包含「今天」时追加 SELECT ... FROM analytics_xxx_stat_today WHERE #{endDate} >= CURDATE() AND #{startDate} <= CURDATE() ``` **含义**: - `*_today`:当前自然日内的 **累计快照**(每个实体最多 1 行) - `*_history`:每个 `stat_date` 一行历史快照(保留 30 天) --- ## 六、scene → event_code → 表 映射 前端传 `scene`,后端枚举见 `AnalyticsScene`,落库 `event_code` 见 `AnalyticsEventCode`。 ### 6.1 用户域 | scene | event_code | 主要影响 | |-------|------------|----------| | `APP_LAUNCH` | `user.launch` | event → DAU、`user_stat` | | `APP_REGISTER` | `user.register` | event → 新增用户、`user_stat.is_new_user` | | `REGISTER_PAGE` | `user.register.page` | 注册漏斗 | | `REGISTER_PHONE` | `user.register.phone` | 注册漏斗 | | `REGISTER_OTP` | `user.register.otp` | 注册漏斗 | | `REGISTER_PASSWORD` | `user.register.password` | 注册漏斗 | | `USER_LOGIN` | `user.login` | event、`user_stat` | | `USER_LOGOUT` | `user.logout` | event、在线时长 | | `USER_HEARTBEAT` | `user.heartbeat` | event、`user_stat.last_active_time`、在线时长 | ### 6.2 商家域 | scene | event_code | 主要影响 | |-------|------------|----------| | `MERCHANT_EXPOSE` | `merchant.expose` | 漏斗曝光、`merchant_stat.expose_count` | | `MERCHANT_CLICK` | `merchant.click` | 漏斗点击 | | `MERCHANT_DETAIL` | `merchant.detail` | 漏斗详情 | | `MERCHANT_CONTACT` | `merchant.contact` | 漏斗电话/导航 | | `MERCHANT_VIEW` | `merchant.view` | 商家 UV、`merchant_stat.visit_uv/pv` | | `MERCHANT_VERIFY` | `merchant.verify` | 核销、转化率分母/分子 | | `MERCHANT_REVIEW` | `merchant.review` | 评价率 | | `PAY_SUCCESS` | `pay.success` | GMV、`merchant_stat.gmv`、转化率 | ### 6.3 内容 / 审核 / 举报 | scene | event_code | 主要影响 | |-------|------------|----------| | `CONTENT_PUBLISH` | `content.publish` | 发布数、`content_stat` | | `CONTENT_INTERACT` | `content.interact` | 互动数(`eventSubtype`: like/comment/share) | | `AUDIT_SUBMIT` | `audit.submit` | 审核提交 | | `AUDIT_PASS` | `audit.pass` | 审核通过 | | `AUDIT_REJECT` | `audit.reject` | 审核驳回 | | `REPORT_SUBMIT` | `report.submit` | `report_record`、举报率分母 | | `REPORT_HANDLE` | `report.handle` | `report_record.status`、举报率分子 | ### 6.4 AI | scene | event_code | 主要影响 | |-------|------------|----------| | `AI_CHAT_START` | `ai.chat.start` | event | | `AI_CHAT_MESSAGE` | `ai.chat.message` | event | | `AI_CHAT_END` | `ai.chat.end` | 对话次数 KPI、`ai_chat_stat` | | (独立接口)ai-request | — | `analytics_ai_request` → 平均响应时间 | --- ## 七、`analytics_event` 字段说明 | 字段 | 说明 | 典型用途 | |------|------|----------| | `event_id` | 幂等 UUID | 防重复上报 | | `event_code` | 事件编码 | 聚合分组 | | `event_subtype` | 子类型 | 互动 like/comment/share;审核 pass/reject;举报处理时传原 report_id | | `user_id` | 用户 | DAU、漏斗下钻 | | `merchant_id` | 商家 | 商家漏斗、GMV | | `target_id` | 目标 ID | 内容 ID、订单 ID | | `content_type` | 1动态 2打卡 3二手 | 内容维度 | | `business_category` | 1–7 经营品类 | 品类 GMV 分布 | | `shop_type` | 1–3 店铺类型 | 商家分类 | | `amount` | 金额(元) | GMV、客单价 | | `duration_ms` | 毫秒 | 心跳/会话时长 | | `device_type` / `channel` / `city` | 设备/渠道/城市 | 画像、地域 TOP10 | | `event_time` | 事件发生时间 | 划分 stat_date | --- ## 八、`analytics_daily_summary` 字段血缘 每行对应一个 `stat_date`(自然日),由 `calculateDailySummary` 写入。 | 字段 | 计算口径(主要来源) | |------|---------------------| | `dau` | `COUNT(DISTINCT user_id)` @ event(当日活跃) | | `mau` | 近 30 日 event 去重活跃 | | `new_user_count` | `user.register` 事件数 | | `register_page_view_count` … `register_success_count` | 注册漏斗各 step 的 event 计数 | | `ai_chat_count` / `ai_chat_user_count` | `ai.chat.end` 次数 / 去重用户 | | `content_publish_count` | `content.publish` | | `content_interaction_count` | `content.interact` | | `merchant_visit_uv` | 商家访问去重 UV | | `merchant_expose_count` … `merchant_contact_count` | merchant_stat 汇总或 event | | `ai_response_duration_total_ms` / `ai_request_count` | `analytics_ai_request` | | `online_user_count` | 跑批快照(实时在线查 `user_stat_today`) | | `pay_user_count` / `today_gmv` / `avg_order_amount` | `pay.success` | | `conversion_rate` / `today_conversion_rate` | 支付用户数 / DAU | | `verify_rate` | 核销数 / 商家访问 UV | | `merchant_review_rate` | `merchant.review` / `merchant.verify` | | `audit_*` / `audit_pass_rate` | 审核 event | | `report_submit_count` / `report_handle_count` / `report_handle_rate` | 举报 event | | `next_day_retention_rate` | T-1 注册用户中 T 日活跃比例(写在前日行) | | `last_7d_new_user_count` / `last_7d_active_user_count` | 滑动窗口 event 去重 | | `total_settled_merchant_count` | merchant_stat 入驻商家数 | --- ## 九、明细表字段与 event 聚合关系 ### 9.1 `analytics_user_stat_*` | 字段 | 来源 | |------|------| | `first_launch_time` / `last_active_time` | event 聚合 / 心跳实时更新 | | `online_duration_min` | heartbeat + logout 的 `duration_ms` 累计 | | `is_new_user` | 当日是否有 `user.register` | | `gender` / `age_group` / `channel` / `city` | 注册或 detail 接口 | **关联**:`user_id`;看板「当前在线」查 `user_stat_today.last_active_time` 近 5 分钟。 ### 9.2 `analytics_merchant_stat_*` | 字段 | 来源 | |------|------| | `visit_uv` / `visit_pv` | `merchant.view` | | `expose_count` … `contact_count` | 漏斗 event | | `verify_count` | `merchant.verify` | | `review_count` / `review_rate` | `merchant.review` / verify | | `gmv` / `pay_count` / `pay_user_count` | `pay.success` | | `verify_conversion_rate` | verify / visit_uv | | `settle_time` / `settle_status` | 入驻 detail | **关联**:`merchant_id`。 ### 9.3 `analytics_content_stat_*` | 字段 | 来源 | |------|------| | `interaction_count` / `like_count` 等 | `content.interact` | | `publish_time` / `status` | `content.publish`、业务状态 | | `audit_status` / `audit_time` | `audit.*` event 或 detail | **关联**:`(content_type, content_id)`。 ### 9.4 `analytics_category_daily_*` 按 `business_category`(1–7)汇总当日 GMV、支付笔数、商家 UV、内容发布/互动。 ### 9.5 `analytics_report_record_*` | 字段 | 说明 | |------|------| | `report_id` | 举报单号(提交时 `event_id`) | | `content_id` / `content_title` / `report_type` | 举报对象 | | `status` | 0 处理中 / 1 已处理 | | `report_time` / `handle_time` | 提交/处理时间 | --- ## 十、报表 API 读表策略 | 能力 | 优先读取 | 回退 / 补充 | |------|----------|-------------| | 看板 8 KPI 卡片 | `daily_summary` + 周期对比 | event 现场聚合 | | 趋势图(多日) | `daily_summary` | 今日按小时查 event | | 商家/注册漏斗 | `merchant_stat_*` / `daily_summary` 漏斗字段 | event | | 漏斗下钻明细分页 | **`analytics_event`** | — | | 用户/商家/内容明细分页 | `*_today` ∪ `*_history` | — | | 留存 cohort | event 跨日 join | `daily_summary.next_day_retention_rate` | | 当前在线(TODAY) | `user_stat_today.last_active_time` | — | | 举报列表 | `report_record_today` ∪ `report_record_history` | — | | AI 平均响应 | `daily_summary` 或 `analytics_ai_request` | — | | 多日 UV 整段去重 | **`analytics_event`** | 勿简单 SUM 每日 UV | **设计原则**: - **快**:KPI、趋势 → `daily_summary` - **细**:分页、TOP → `*_stat` - **准**:去重、下钻、cohort → `analytics_event` --- ## 十一、KPI 卡片数据链路示例 ### 11.1 今日 DAU ``` APP_LAUNCH / 活跃行为 → analytics_event (user_id, event_time) → calculateDailySummary → daily_summary.dau → GET /analytics/dashboard/summary → activeUser.value ``` 多日周期:`countActiveUsersInRange` 直接扫 event 整段去重。 ### 11.2 当前在线 ``` USER_HEARTBEAT (durationMs) → analytics_event → user_stat_today.last_active_time(实时更新) → countOnlineSince(5min) / summary.onlineUser ``` 仅 `period=TODAY` 为实时;其他周期不展示 5 分钟窗口值。 ### 11.3 举报处理率 ``` REPORT_SUBMIT → event + report_record_today REPORT_HANDLE → event + report_record 更新 status=1 → daily_summary.report_handle_rate = handle / submit → content-report.summary.reportHandleRate ``` ### 11.4 商家评价率趋势 ``` MERCHANT_REVIEW / MERCHANT_VERIFY → merchant_stat.review_rate(商家维度) → daily_summary.merchant_review_rate(平台日) → merchant-report.reviewRateTrend ``` --- ## 十二、代码与 SQL 文件索引 ### 12.1 核心 Java 类 | 职责 | 类 | |------|-----| | 埋点写入 | `AnalyticsTrackServiceImpl` | | 明细存取路由 | `AnalyticsDetailStoreServiceImpl` | | 跑批统计 | `AnalyticsStatisticsServiceImpl` | | 零点归档 | `AnalyticsArchiveServiceImpl` | | 看板查询 | `AnalyticsDashboardServiceImpl` | | 用户/内容/商家报表 | `Analytics*ReportServiceImpl` | | scene / event 枚举 | `AnalyticsScene`、`AnalyticsEventCode` | ### 12.2 Mapper / SQL | 文件 | 用途 | |------|------| | `AnalyticsEventMapper.java` | event 聚合 SQL(@Select) | | `AnalyticsDashboardMapper.xml` | 看板趋势、漏斗、留存 | | `AnalyticsUserReportMapper.xml` | 用户报表 | | `AnalyticsContentReportMapper.xml` | 内容报表 | | `AnalyticsMerchantReportMapper.xml` | 商家报表 | | `AnalyticsFunnelMapper.xml` | 漏斗下钻 | | `AnalyticsArchiveMapper.xml` | 归档 / TRUNCATE | ### 12.3 定时任务(XXL-JOB) | Job 名称 | 建议 Cron | 说明 | |----------|-----------|------| | `analyticsArchiveDaily` | `0 0 0 * * ?` | 明细 today → history | | `analyticsCalculateTodayHourly` | `5 5 * * * ?` | 当日准实时汇总(避开零点归档) | | `analyticsCalculateYesterdayDaily` | `0 0 2 * * ?` | 前日完整汇总 | | `analyticsCalculateRetention` | `0 0 3 * * ?` | 次日留存写前日行 | --- ## 十三、运维与数据一致性 ### 13.1 新环境初始化 1. 执行 `analytics_schema.sql` 2. 配置 XXL-JOB 上述 4 个任务 3. 前端接入埋点后,可手动 `POST /analytics/stat/calculate` 补历史日 ### 13.2 旧环境升级 执行 `analytics_tables_dashboard_upgrade.sql`,必要时按脚本末尾说明将旧单表 RENAME 为 `*_today`。 ### 13.3 一致性说明 | 现象 | 原因 | 建议 | |------|------|------| | 明细与 event 短暂不一致 | 实时写 today,跑批后按 event 覆盖 | 以跑批后为准 | | 看板无数据 | 未跑 `calculate` 或 `daily_summary` 无该行 | 补跑跑批 | | 今日与历史拼接断层 | 未跑归档或 today 已 TRUNCATE | 检查 archive 任务 | | 多日 UV 偏大 | 误用 SUM(日 UV) | 改用 event 周期去重 | ### 13.4 手动运维接口 | 接口 | 用途 | |------|------| | `POST /analytics/stat/calculate` | 指定 `statDate`、`scope` 跑批 | | `POST /analytics/stat/archive` | 手动触发昨日归档 | --- ## 十四、与旧埋点体系的关系 - **新体系**:`/analytics/front/*` + 本文档所述表,代码在 `shop.alien.store.controller.analytics` 包下。 - **旧体系**:`@TrackEvent` 注解 + `POST /track/event`,见 [`埋点接口清单.md`](./埋点接口清单.md),与 analytics 表 **相互独立**。 - 运营看板 **仅消费新体系** 数据;旧埋点如需纳入看板,需增加 scene 上报或同步任务。 --- ## 十五、相关文档 | 文档 | 内容 | |------|------| | [`前端埋点接入指南.md`](./前端埋点接入指南.md) | 前端 scene、请求示例、看板 API | | [`埋点接口清单.md`](./埋点接口清单.md) | 旧 @TrackEvent 接口列表 | | `analytics_schema.sql` | 完整 DDL | | `analytics_tables_dashboard_upgrade.sql` | 旧库增量升级 | --- **维护说明**:表结构或跑批逻辑变更时,请同步更新本文档与 `analytics_schema.sql` 头部注释。