首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >门店经营看板为什么越查越慢:预聚合、增量统计与缓存设计

门店经营看板为什么越查越慢:预聚合、增量统计与缓存设计

原创
作者头像
用户5598620
发布2026-09-12 09:08:08
发布2026-09-12 09:08:08
840
举报

做门店数字化的人大概都遇到过:经营看板刚上线时秒开,数据量一上来,老板点一下"今日销售"要转 3 秒,点"本月各门店对比"直接超时。原因是看板背后在实时跑聚合查询——每次打开都对原始流水表做全量 GROUP BY。门店流水一天几千到几万条不算多,但按年累计就是百万级,再叠加多门店、多维度,实时聚合必然变慢。本文讲清"预聚合 + 增量统计 + 缓存"这套组合拳,让看板从秒级回到毫秒级。

一、为什么实时聚合会越来越慢

看板常见的查询长这样:

代码语言:sql
复制
-- 每次打开看板都执行:扫全表 + 全量分组
SELECT store_id, SUM(amount), COUNT(*)
FROM trade_flow
WHERE created_at >= '2026-09-01'
GROUP BY store_id;

问题在于:trade_flow 是流水明细表,行数随时间只增不减。GROUP BY 要扫描该时间窗内的所有行并做分组计算,查询耗时随数据量线性增长。等到流水过百万行、窗口跨度又大,单次聚合就是几百毫秒到几秒,看板体验直线下降。而且老板会反复刷新看板,等于把同样的聚合算了一遍又一遍。

二、第一板斧:预聚合(把"算过的"存下来)

预聚合的思路:不要每次现算,而是提前把"按天 × 门店 × 指标"算好存进汇总表。看板只查汇总表,几行数据秒回。

代码语言:sql
复制
-- 日级预聚合表
CREATE TABLE daily_stat (
  stat_date  DATE,
  store_id   INT,
  order_cnt  INT,
  amount_sum DECIMAL(12,2),
  PRIMARY KEY (stat_date, store_id)
);
代码语言:sql
复制
-- 凌晨批量生成前一天汇总(也可以每 N 分钟增量跑)
INSERT INTO daily_stat
SELECT stat_date, store_id, COUNT(*), SUM(amount)
FROM trade_flow
WHERE stat_date = '2026-09-11'
GROUP BY stat_date, store_id;

看板默认只看最近 30 天时,最多扫 30 行日汇总,而不是几十万行流水。预聚合粒度要和看板最常用的时间维度对齐:日级是底线,小时级用于当日实时看板。

三、第二板斧:增量统计(当日数据单独算)

预聚合解决"历史数据",但"今天"的数据还在不断产生,无法等到明天。增量统计的思路:历史走预聚合,当日走实时增量,两者相加。

代码语言:sql
复制
-- 当日实时部分:只算今天
SELECT store_id, COUNT(*), SUM(amount)
FROM trade_flow
WHERE stat_date = CURRENT_DATE
GROUP BY store_id;

-- 历史部分:查预聚合表
SELECT store_id, COUNT(*) + ? , SUM(amount) + ?
FROM daily_stat
WHERE stat_date BETWEEN ? AND CURRENT_DATE - 1
GROUP BY store_id;

当日流水量小(几千条),实时 GROUP BY 毫秒级完成;历史走预聚合表也毫秒级。看板接口把两部分结果合并返回即可。注意"当日"要按门店时区算,别用服务器 UTC 时间,否则凌晨 0~8 点数据会串天。

四、第三板斧:缓存(同样的结果别算两遍)

即使预聚合了,老板反复刷新、多个门店同时打开同一看板,仍会重复查库。再加一层缓存:

代码语言:javascript
复制
// 以 维度+时间窗+版本号 为 key 缓存 30~60 秒
const key = `dash:${storeId}:${range}:${dataVersion}`;
const hit = cache.get(key);
if (hit) return hit;

const data = computeDashboard(storeId, range);
cache.set(key, data, 60); // TTL 60s
return data;

缓存 key 里放一个 dataVersion:每当增量统计写入新数据就 +1,看板端轮询或接口返回版本号,版本变化才强制刷新。这样既能缓存,又不会让老板看到明显过期的数据。热门店的看板 99% 的请求都打在缓存上,数据库压力几乎归零。

五、进阶:多门店对比与趋势要分层

"多门店横向对比"和"趋势曲线"对性能的要求不同:

  • 门店数固定(几十家),多门店对比 = 一次小范围 GROUP BY,预聚合表直接扛住。
  • 趋势曲线(近 90 天每天)需要 90 个点的数据,直接用日汇总表即可。
  • 只有"老板自定义任意时间窗 + 任意门店组合"这种自由报表才可能全表扫,这种场景要么限制窗口上限(如最多 180 天),要么进数仓用列存/OLAP 引擎,不适合在线看板直查。

六、踩坑清单

现象

解法

只有预聚合没有当日增量

今日数据看不到

当日实时算 + 历史预聚合相加

按 UTC 计算"当日"

凌晨数据串到昨天

按门店本地时区分天

缓存 key 没有版本号

数据更新了看板还显示旧值

写入新数据时 version+1

预聚合粒度太粗

看板要小时级但只有日级

当日用小时级预聚合

全表扫没有上限

任意大窗口查询拖垮库

限制时间窗或走 OLAP

七、工程落地建议

落地顺序建议从"预聚合 + 当日增量"开始,这是投入产出比最高的一步,纯 SQL 就能完成;看板并发高再加缓存层。定时任务生成预聚合时,注意错峰(避开业务高峰)、支持重跑(某天数据修正后能重新生成),并给预聚合表加唯一键防止重复插入。这套方案不依赖特定存储,MySQL、PostgreSQL 都适用,团队可以快速上手;数据量继续增长后再考虑引入列式存储或 OLAP 引擎。无论用哪种方式,核心都是"别让看板每次现算全量数据"。

八、复盘清单

  • 历史查询是否走了预聚合表,不再扫流水明细
  • 当日数据是否单独增量计算并与历史合并
  • 是否按门店本地时区分天
  • 缓存是否带版本号、能感知数据更新
  • 是否有兜底限制,防止任意大窗口查询

结语

看板变慢不是数据库不行,而是架构上"实时聚合"这个设计从根上就不适合反复查询。预聚合、增量统计、缓存三层叠加,能把看板从秒级压到毫秒级,实现成本低、见效快。希望这套组合拳能帮你把经营看板做得又快又稳。

以上为通用后端架构实践分享,具体功能以各平台官方实时文档为准。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、为什么实时聚合会越来越慢
  • 二、第一板斧:预聚合(把"算过的"存下来)
  • 三、第二板斧:增量统计(当日数据单独算)
  • 四、第三板斧:缓存(同样的结果别算两遍)
  • 五、进阶:多门店对比与趋势要分层
  • 六、踩坑清单
  • 七、工程落地建议
  • 八、复盘清单
  • 结语
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档