高频聚合报表必须采用预计算+缓存+分级查询组合策略,否则数据库无法承载;应使用物化视图或汇总表替代实时GROUP BY,精简字段、按业务节奏刷新,配合Redis缓存固定参数结果,并分级控制明细下钻与查询范围。

用物化视图或汇总表替代实时 GROUP BY
报表里大量 SUM、COUNT、GROUP BY 跨订单/用户/商品大表时,每次执行都是全表扫描。PostgreSQL 的 MATERIALIZED VIEW、Oracle 原生物化视图、MySQL 用 REPLACE INTO summary_sales SELECT ... GROUP BY 定时跑批,是最稳的解法。
关键点:
- 汇总表字段只留强依赖维度(如
city、date、sales_amount),删掉所有非必要字段,写入和查询都更快 - 按业务节奏刷新:T+1 报表用每日凌晨跑批;小时级看板用每小时定时任务触发
- 避免在汇总表上建过多索引——它主要是读多写少,但冗余索引会拖慢写入
Redis 缓存参数确定的聚合结果
同一份日报,运营反复刷屏,后几次请求完全没必要走 DB。对参数固定、时效宽松的接口(比如 report:sales_daily:20260720:city_shanghai),直接缓存结果。
注意三点:
- Key 必须包含业务标识 + 日期 + 关键参数哈希,不能只用日期,否则城市切换就命中错误缓存
- TTL 设 15 分钟足够,再配合主动刷新:ETL 完成后发消息清空当天所有相关 Key,或直接写新值
- 前端加
debounce,防止用户连点触发 5 次相同请求
区分报表等级,限制明细下钻粒度
不是所有“查看详情”都要查千万行订单明细。二级报表默认只返回 1000 条,且强制带 WHERE created_at >= '2026-07-01' 和索引字段过滤;三级专项分析走离线队列,不挤占在线资源。
常见陷阱:
- 没加时间范围的明细查询,哪怕加了索引也容易因数据量过大触发排序溢出或内存不足
- 前端未做分页控制,后端又没设
LIMIT,一次查出 50 万行,连接池瞬间打满 - 把“导出 Excel”和“页面展示”共用同一套 SQL,导出应走异步任务+临时表,而非直连主库
清理无效查询与索引,别让历史代码拖垮现在
很多压力来自没人管的旧逻辑:测试脚本轮询、废弃报表仍被定时调用、监控工具无节制查 pg_stat_activity。
动手前先确认:
- 用
pg_stat_statements查 TOP 20 高频低效 SQL,逐条问业务方“这个还在用吗?” - 删掉长期无访问的报表接口,或加配置中心开关,一键关停
- 检查索引是否重复:
pg_indexes对比字段组合,删掉前缀重叠的联合索引(比如已有(status, created_at),再建(status)就多余)
最易被忽略的是:物化视图刷新本身也会锁表、占资源,别把它设成每分钟刷新一次——业务根本不需要那么高实时性。

















