如何对大量数据做聚合统计?

有一个错题本统计功能需求,当前我的做法是用mongodb一个集合 exercise 来保存做题记录,每做一道题就保存一条记录,数据用aggregate进行聚合统计。目前exercise 集合已经有2000多万记录,而且增长速度很快,一条记录结构如下:

{
    "_id" : ObjectId("58856c54c10da3925edc9a4b"), 
    "eid" : NumberLong(1), // 试题ID
    "right" : NumberLong(1), // 是否正确
    "scene" : NumberLong(1), // 场景
    "uid" : NumberLong(663148), // 用户
    "total" : NumberLong(1), // 试题总分
    "score" : NumberLong(1), // 用户得分
    "rate" : NumberLong(100), // 正确率
    "date" :  ISODate("2017-01-23T12:17:00.000Z"), // 做题时间
    "subject" : NumberLong(1), // 科目
    "class" : NumberLong(1), // 班级
    "grade" : NumberLong(1), // 年级
    "school" : NumberLong(1), // 学校
    "tags" : [ 
        {
            "tagID" : NumberLong(39544), // 章节ID
            "level" : NumberLong(1) // 章节层级
        }, 
        {
            "tagID" : NumberLong(39621),
            "level : NumberLong(1)
        }
    ]
}

需求如下:
(1)根据年级,科目,日期,学校查找错题列表,并且每一道错题要统计做错次数
(2)根据年级,科目,学校,统计每个场景错题数目
(3)根据年级,科目,教材统计教材下各个章节对应所有错题做错总次数

目前对学校加了索引,但当学校数据量有几百万时,对于以上需求查询速度很慢,不知道其他大网站是怎么设计的,查询速度很快。求有经验的大神赐教

阅读 10k
5 个回答

首先是索引的问题,你的三个查询对应的三个索引分别是:

{grade: 1, subject: 1, date: 1}
{grade: 1, subject: 1, school: 1}
{grade: 1, subject: 1, "tags.tagId": 1}

但是索引并不能完全解决你的问题。心里要有一个概念,凡是涉及到统计的问题,涉及的数据量越多,速度越慢,毕竟你是要一次读取这么多数据,其速度肯定是无法和查询几条记录的速度相比的。
但是练习结果是随着人做不断增多的,如果每次都对全部数据做一次统计,数据量越来越大,势必越来越慢。所以问题变成如何控制每次统计的数据数量?以下两个方面都应该有所考虑:

  1. 限制回溯的天数(比如只统计1年内的?)。
  2. 按不同的粒度预聚合。

预聚合是很常见的处理时序数据增长的手段。以第一个问题为例:

(1)根据年级,科目,日期,学校查找错题列表,并且每一道错题要统计做错次数

假设每天有10道这样的错题,100天过去就会有1000道。这时候你的查询一次要统计1000条记录才能得到结果;
如果我每天结束时按天做预聚合,100天过去后我就只有10条记录,里面记录了每天的统计结果。这时候就只需要把这100条记录的结果汇总,就是我要的结果;
进一步,如果有必要还可以考虑月、年等聚合粒度,这样在跨长时间的查询中就会有更多优势。

谢邀,本人水平有限,回答仅供参考。

慢的原因可能在于你建索引的字段并不合适,理论上应该是那些当成查询条件次数多的字段建立索引,根据你的需求就是年级和科目,如果这两个字段是查询必带条件,那么可以考虑把这两个字段建立一个联合索引。

其次如果不要求实时查看统计结果,可以把统计结果另建表存储,并对统计结果表定期更新,界面显示时去查询结果表。

可以先看下你的索引是如何建立的.. 然后使用explain 分析一下执行过程

提问楼上的,explain只能分析sql语句的执行速度吧,但是这个是mangodb,这个是非关系型数据库,怎么分析

aggregate+索引 用explain来分析下你的语句,找到最优解 探读

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏