我正在尝试汇总100个帐户的数据,为期14-15个月,按年和月分组。
然而,查询性能非常糟糕,需要22-27秒。该集合中目前有超过1500万条记录,我有一个匹配条件的索引,可以看到优化程序使用它的explain()
。
我尝试在下面的查询中添加另一个索引,在添加索引后,查询现在需要超过50秒!即使我从查询中删除了排序,也会发生这种情况。
我非常困惑。我认为因为分组不能使用索引,如果预先对集合进行排序,那么分组可能会快得多。这个假设是否正确?如果没有,我还有其他选择吗?我可以承受多达5秒的查询性能,但仅此而已。
//Document Structure
{
Acc: 1,
UIC: true,
date: ISODate("2015-12-01T05:00:00Z"),
y: 2015
mm: 12
value: 22.3
}
//Query
db.MyCollection.aggregate([
{ "$match" : { "UIC" : true, "Acc" : { "$in" : [1, 2, 3, ..., 99, 100] }, "date" : { "$gte" : ISODate("2015-12-01T05:00:00Z"), "$lt" : ISODate("2017-02-01T05:00:00Z") } } },
//{ "$sort" : { "UIC" : 1, "Acc" : 1, "y" : -1, "mm" : 1 } },
{ "$group" : { "_id" : { "Num" : "$Num", "Year" : "$y", "Month" : "$mm" }, "Sum" : { "$sum" : "$value" } } }
])
答案 0 :(得分:0)
我建议你做的是制作一个脚本(可以在nodejs中),用于聚合不同集合中的数据。当您有这些长查询时,建议使用包含聚合数据和查询的不同集合。
我的第二个建议是在这个聚合集合中创建一个组合索引并按正则表达式搜索。在你的情况下,我会创建一个包含accountId:period
的索引。例如,对于帐户1和2016年2月,索引类似于1:201602
。
然后,您将能够通过帐户和时间戳使用正则表达式执行查询。就像你想要帐户1的2016年寄存器一样,你可以做类似的事情:
db.aggregatedCollection.find{_id : \1:2016\})
希望我的回答很有帮助