表里存放的都是原始数据,那么根据不同参数的复杂的聚合统计数据的图表应该怎么做?

随便举个简单的例子:
有个订单表,表里有门店id,商品id,售价,订单生成时间
如果需要做一个图表的api,用于展示:

  • 所有门店,在指定时间范围内销售额/订单量的排名
  • 指定门店,在指定时间范围内,每日销售额的增长率
  • 所有门店,在指定时间范围内,日销售额达到阀值的天数

这三个需求也是随便想的,我知道用sql+编程语言服务端处理,都能做到,但是效率很低、对数据库压力很大,接口响应很慢,不是吗?
而且我举的例子算很简单了,就一张表里做文章。实际业务,表结构可能复杂得多,可能还有门店归属公司、销售人员、产品所属厂商等等,都有对应的统计需求

比如我们增加一个元素:店员表
然后一个新需求是——

  • 指定门店,在指定时间范围内,每天的人均销售额(用于考察用人成本)

补充说明:店员人数是会变化的,要求算人均销售额的时候,按店员的入职时间,以及离职时间,来计算目标那一天的店员数量。
你们说,这种需求,图表怎么搞?比如api一次性要返回一个月的数据(横坐标有30天)。
再假如,一个数据中心的页面上,有8个这么复杂的图表。光sql聚合分组查询,就要查多少秒?

请问这种需求该如何实现?

目前尝试了中间缓存表,就是把图表要展示的数据定义成表,按最小时间单位,使用计划任务,主动计算存表。然后图表的api中仅读取中间缓存表来得到数据,而不去访问原始数据。
但这样做,太死板了,很不灵活。需求一变动,就得改中间表,删老数据,重新生成老数据。
我想,这不是一个好主意。
请社区大佬指教,谢谢~

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 7

性能没达到瓶颈之前,不要想着效率会很低。除非你的sql真的很慢了,而且sql真的很慢了,也不要第一时间考虑去加缓存,应该是优化sql。

我知道用 sql + 编程语言服务端处理,都能做到,但是效率很低、对数据库压力很大,接口响应很慢,不是吗?
反对,效率低,压力大,接口慢没有数据表示出来。程序员都是看数据,一般后台qps又不大,你又没做基准测试,就一口咬定不行。你去做,真的慢了,就去做学习一下sql的优化。

当你达到了sql瓶颈,你再来问这个问题才有意义。杀鸡焉用牛刀

4年前 评论

你们说,这种需求,图表怎么搞?比如 api 一次性要返回一个月的数据(横坐标有 30 天)。

一个月的数据,这种数据不会变嘛,历史数据。那就明显是读多于写,那么可以考虑使用MyISAM引擎,而且要让该引擎的表是静态表格式,就会达到一个读很流程快速的状态。

或者你说,不行,现在表已经是InnoDB了,还有数据在写入表。那么,做读写分离是不是能搞定。我们让写表写入数据更快,读表读取数据更快,是不是又优化了一步。

在这里我也是班门弄斧,因为我压根对你的系统一无所知。但是你可以主动去获取知识,比如《高性能Mysql》。

4年前 评论

试试这个AnalyticDB

4年前 评论
萧晔离 4年前
hello-bug (作者) 4年前

我建议新建一个表。 门店 id,日期 ,订单数量,订单金额

4年前 评论

分析用户的真正需求,会为你带来想象不到惊喜。所以一定要重视需求分析!

:relaxed:首先,你说这些业务都是你自己想的,而不是和客户那分析出来的。

:grin:其次,对于需求变更,重新写代码或者更新代码来实现需求很正常,在设计系统时需要考虑可扩展性,而做不到一次编程,业务随意变。

:grinning:现在我认为上面的问题都是真实的需求,让我们一起来想想解决方案。

  • 虽然我是做技术的,但是我一般都会先在业务角度来解决,比如上面提到的三个需求,最小单位是天,时间范围不确定。但每天的数据都是多条的,是否可以在每天固定的时间,比如打样时间、固定晚上12点开始对当天的数据进行统计、整合呢?直接放到一个中间表中。
  • 和客户详细沟通需求,了解下时间范围的需求点,分析用户真实需求,比如用户常用的是不是按周、月、季度来看呢?如果是这样那么就可以提前对数据进行统计了,这样至少可以满足80%的查询就可以了。
  • 慢的原因是因为数据量非常大,既然你这么看重速度,那么数据量应该是非常大的,那么在技术上如何在保证数据正确的前提下,减少数据量是否可行呢,比如之前每天 500 笔销售单,我们可以每天合计,变成一笔合计。

“目前尝试了中间缓存表,就是把图表要展示的数据定义成表,按最小时间单位,使用计划任务,主动计算存表。然后图表的 api 中仅读取中间缓存表来得到数据,而不去访问原始数据。

如果能分析好用户的需求,通过这种方式完全可以解决你担心的问题了。我们在做财务系统的时候,或者现在成熟的财务系统,比如用友,他用采用的复式记账法,一个报表的统计维度很大,而且关联的数据项特别多。那它每晚都会运行很多计划任务,就是在做这样的工作。但即使这样,在查询个别报表时,依然会非常慢,但至少 80% 以上的查询还是比较快的,你看下它的表结构,很多中间表。

4年前 评论

Mark一下,看看有没有其他方案~~

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!