我是mongo的新用户(具有丰富的mysql经验),似乎有一些有趣的优点和缺点。显然,优点是您可以保存的数据大小以及写入记录的速度。我有一个应用程序,我正在写一个集合的许多日志,到目前为止我有大约7米。我的问题是,看似简单的查询需要很长时间真正。让我解释一下。
我的收藏有700万份文件:
> db.alpha2.count()
7257619
现在我想要计算给定cid的所有记录,并且时间戳小于某个数字(此示例将来会有时间戳,因此它应计算所有内容):
> db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).count()
7257619
这是问题查询,需要一个完整的 58秒才能将此号码返回给我!从概念上讲,这是一个非常简单的查询,在sql世界中可能与此类似:
select count(*) from alpha2 where cid=2636518 and ts<1446457607
我没有等效表,但我认为根据我的经验在mysql中运行时间不到0.1秒。那我该怎么办?我计划对远大于7m记录的数据集进行大量聚合计数。我也做了一些稍微努力的东西(地图缩小),而且情况要糟糕得多(几分钟)。我需要这个不到一秒钟。我究竟做错了什么?这是mongo的预计时间成本吗?
在我对上述查询进行计时之前,我在ts值上加了一个索引:
db.alpha2.ensureIndex({ts:1})
答案 0 :(得分:4)
为了确定count()
,MongoDB必须找到所有匹配的文档。
您可以explain()查询以查看索引的使用方式:
db.alpha2.find({'ts': {'$lt': 1446457607}, 'cid': '2636518'}).explain()
特别想要最小化nscannedObjects
(扫描的文档数量)。
您最好的案例标准方案是对计数中涉及的所有字段建立索引(并确保索引适合可用的RAM)。
因此,您的索引也应包含cid
:
db.alpha2.ensureIndex({ts:1, cid:1})
如果您经常进行计数,如果适用于您的用例,您可能会通过incremental map/reduce之类的流程更好地存储和更新这些数据。