# 国家数据大屏数据查询技术文档 ## 目标 国家数据大屏接口 `/console/datav/country-dashboard` 原来在页面请求时实时扫描订单、用户、游戏流水和 wallet 分表。线上慢查询主要集中在 `wallet_gold_asset_record_1..12` 的游戏流水、游戏人数统计。当前改为 SQL 指标预聚合,页面优先查询汇总表;汇总缺失或请求范围不符合预聚合口径时,才回退原实时 SQL。 ## 查询入口 - Controller: `DatavRestController#countryDashboard` - Service: `CountryDashboardServiceImpl#query` - DAO: `CountryDashboardDAO` - Mapper: `CountryDashboardDAO.xml` 查询参数: - `periodType`: `DAY` / `WEEK` / `MONTH` / `ALL` - `startDate`, `endDate`: 闭区间日期,后端转为 `[startDate 00:00:00, endDate + 1 day 00:00:00)` - `statTimezone`: 统计时区,默认 `Asia/Riyadh`,支持 `Asia/Riyadh` / `UTC` / `Asia/Shanghai` - `countryKeyword`: 国家码或国家名模糊匹配 - `sysOrigin`: 系统来源,预聚合查询必须传 ## 预聚合表 ### `country_dashboard_daily_metric` 日级 SQL 指标表,按 `stat_date + sys_origin + country_code` 唯一。 用途: - 保留日级汇总结果。 - 作为 `ALL` 周期金额汇总的数据来源。 - 作为历史回填和排查的基础日表。 ### `country_dashboard_period_metric` 周期汇总表,按 `period_type + period_key + stat_timezone + sys_origin + country_code` 唯一。 周期键示例: - `DAY`: `2026-05-07` - `WEEK`: `2026-W19` - `MONTH`: `2026-05` - `ALL`: `ALL` 页面查询优先读取这张表。 ### `country_dashboard_period_user_metric` 周期用户去重明细表,按 `period_type + period_key + stat_timezone + sys_origin + country_code + user_id + metric_type` 唯一。 当前维护的 `metric_type`: - `COUNTRY_NEW_USER`: 新增用户人数 - `LUCKY_GIFT_USER`: 幸运礼物用户人数 - `GAME_USER`: 游戏用户人数 `WEEK/MONTH/ALL` 的人数类指标不再从日表简单相加,而是基于这张明细表聚合,避免同一个用户跨多天被重复计算。 ## 查询路由 `CountryDashboardServiceImpl#shouldUsePrecomputedMetrics` 会先判断是否能走预聚合。 走预聚合的条件: - `sysOrigin` 不为空。 - 对应 `statTimezone` 的周期预聚合已经存在。 - `DAY`: 查询范围内每一天都有 `country_dashboard_period_metric` 数据。 - `WEEK/MONTH`: 查询范围必须按周期边界对齐,当前未结束的周/月允许到今天。 - `ALL`: 无 `startDate/endDate` 时固定走 `period_type=ALL, period_key=ALL`。如果汇总表未回填,返回空汇总,不再回退全历史实时扫描。 `DAY/WEEK/MONTH` 不满足条件时回退原实时 SQL,保证数据不因预聚合缺失而返回错误。`ALL` 不回退实时 SQL,是为了避免一次后台点击触发全历史 wallet 分表扫描。 ## 刷新任务 任务类:`CountryDashboardDailyMetricTask` 默认任务: - 每 10 分钟刷新最近 1 天:`red-circle.country-dashboard.refresh-today-cron` - 每天 00:20 刷新最近 8 天:`red-circle.country-dashboard.refresh-recent-cron` 默认平台: ```yaml red-circle: country-dashboard: refresh-sys-origins: LIKEI ``` 需要刷新多个平台时配置为逗号分隔,例如: ```yaml red-circle: country-dashboard: refresh-sys-origins: LIKEI,TARAB ``` 刷新链路: 1. 按利雅得时区刷新日表 `country_dashboard_daily_metric`。 2. 按配置的统计时区刷新对应 `DAY` 周期表和用户去重明细。 3. 按配置的统计时区刷新受影响的 `WEEK`、`MONTH`。 4. 基于同一 `stat_timezone` 下已存在的 `DAY` 周期表和日级用户明细刷新 `ALL`。 默认刷新时区: ```yaml red-circle: country-dashboard: refresh-timezones: Asia/Riyadh,UTC,Asia/Shanghai ``` ## 指标来源 SQL 预聚合指标: - 新增用户:`user_base_info` - 新用户充值、官方充值、Google 充值:`order_purchase_history` - MifaPay 充值:`order_user_purchase_pay` - 代理充值:`likei_wallet.user_freight_balance_running_water` - 工资兑换:`user_salary_account_running_water`, `user_salary_diamond_running_water` - 幸运礼物流水/返奖:`game_lucky_gift_count` - 游戏流水/返奖:`wallet_gold_asset_record_1..12`, `game_lucky_box_count` - 游戏人数:`country_dashboard_period_user_metric` 的 `GAME_USER` 仍实时从 Mongo 聚合的指标: - 礼物消耗:`gift_give_running_water` - 幸运礼物主播分成:`gift_give_running_water` - 日活:`user_daily_active_log` - 留存:`user_daily_active_log` + 注册 cohort ## 上线和回填 上线前可以先执行: - `sql/20260507_country_dashboard_daily_metric.sql` - `sql/20260507_country_dashboard_period_metric.sql` - `sql/20260508_country_dashboard_period_metric_timezone.sql` 为避免遗漏,console 的刷新和手动回填入口会先执行同等的 `CREATE TABLE IF NOT EXISTS` 检查,再写入预聚合数据。 首次上线后,预聚合表为空时接口会回退实时 SQL。为了尽快切到预聚合,需要先回填最近常用查询范围,例如最近 8 天、当前周、当前月。 `ALL` 的数据由已回填的日表和日级用户明细汇总而来。如果需要后台“全部”展示完整历史,必须先完成历史日数据回填;否则 `ALL` 只代表当前已经进入预聚合表的数据范围。 手动回填入口: ```bash curl -X POST 'http://127.0.0.1:{console_port}/console/datav/country-dashboard/backfill?startDate=2026-04-08&endDate=2026-05-07&sysOrigin=LIKEI' ``` 该入口默认回填 `Asia/Riyadh`、`UTC`、`Asia/Shanghai` 三个统计时区。需要指定时区时可以传: ```bash curl -X POST 'http://127.0.0.1:{console_port}/console/datav/country-dashboard/backfill?startDate=2026-04-08&endDate=2026-05-07&sysOrigin=LIKEI&statTimezones=Asia/Riyadh,UTC,Asia/Shanghai' ``` 该入口会按天重算日表,并按每个 `stat_timezone` 重算 `DAY` 周期,再刷新受影响的 `WEEK`、`MONTH` 和 `ALL`。 ## 验证 SQL 检查某天是否已刷新: ```sql SELECT stat_date, sys_origin, COUNT(1) FROM country_dashboard_daily_metric WHERE sys_origin = 'LIKEI' GROUP BY stat_date, sys_origin ORDER BY stat_date DESC; ``` 检查周期汇总: ```sql SELECT stat_timezone, period_type, period_key, sys_origin, COUNT(1) FROM country_dashboard_period_metric WHERE sys_origin = 'LIKEI' GROUP BY stat_timezone, period_type, period_key, sys_origin ORDER BY stat_timezone, period_type, period_key DESC; ``` 检查用户去重明细: ```sql SELECT stat_timezone, period_type, period_key, metric_type, COUNT(1) FROM country_dashboard_period_user_metric WHERE sys_origin = 'LIKEI' GROUP BY stat_timezone, period_type, period_key, metric_type ORDER BY stat_timezone, period_type, period_key DESC, metric_type; ```