我试图从集合中获得聚合的毫秒(< second)响应时间。但是,即使数据量很小(约200MB),它目前也需要3-5秒。我对此集合的预期生产数据大约为每个碎片100GB。 我已经检查了以下内容 - 当我在每个分片上单独尝试查询时,响应时间相同。 - 检查了分析输出,我所能看到的只是高timeLockedMicros和numYield。 - 在MMS图表中也找不到任何异常。 我觉得这里有些愚蠢的东西。任何帮助进一步分析这一点非常感谢。我的群集和收集详细信息在下面提供
群集 - 34 GB的6个节点,4台核心机器(AWS m2.2xlarge) 数据大小 1,285 MB(每个碎片213 MB) 记录数= 550万(每个碎片约1 M)
记录样本
{
"_id" : {
"ItemID" : 105182,
"DeviceType" : 16,
"ItemVersionID" : 117971,
"Timestamp" : ISODate("2014-11-14T00:00:00Z"),
"RecordType" : 1
},
"Dim1ID" : 102260,
"Dim2ID" : 313,
"Dim3ID" : 1,
"actionType" : {
"1" : 66,
"47" : 66,
"42" : 72,
"46" : 130
}
}
查询
db.AggregateCollection.aggregate({ "$group" : { "_id" : { } , "type1" : { "$sum" : "$actionType.1"} , "type2" : { "$sum" : "$actionType.2"}}})
个人资料统计信息(来自一个分片)
"keyUpdates" : 0,
"numYield" : 79,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(2981456),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(3756),
"w" : NumberLong(4)
}
},
"responseLength" : 157,
"millis" : 3268,
"execStats" : {
},
更新 谢谢你的快速回应。 Apreciate它。我喜欢你的新数据模型和索引。但是,我担心这不适合我目前的数据,因为, - 99%的记录将具有actionType.1和的soem值 - 99%的查询将选择actionType.1 因此,actiionType.K上的索引对我的猜测不会太大。
正如你在#2& #3,我们已经在使用Spark集群进行预聚合,它提升了MongoDb。
关于我的查询的更多信息 我之前分享的查询只是一个示例,仅用于对性能进行基准测试。我的实际查询将在一个或多个文件上的Timestamp和$ group上匹配$。 典型的生产查询将是30天的数据。目前我的收藏只有15天的数据。我的目标是获得30天数据的亚秒响应时间
顺便说一下,我今天做了一些分析 我把碎片转储了,然后在MacBook上安装的本地mongo中恢复。相同的查询仅用了2秒钟(在AWS isntance中花了4秒) 这没有任何意义,因为AWS实例至少比MacBook强大4倍(CPU和内存) MacBook Air - http://www.cpubenchmark.net/cpu.php?cpu=Intel+Core+i5-4250U+%40+1.30GHz AWS m2.2xlarge实例 - http://www.cpubenchmark.net/cpu.php?cpu=Intel+Xeon+E5-2665+%40+2.40GHz我怀疑碎片化是因为AWS mongo实例中的数据在过去15天内通过应用程序填充。所以我将AWS mongo上的转储作为单独的集合重新导入。对这个新系列的查询耗时2s,与MAcBook速度相当。碎片化是肯定的一个原因。我打算稍后对碎片做更多的研究。 尽管对碎片进行了碎片整理,但与我的MacBook相同的时间这一事实并不合理,因为AWS isntance强大了4倍。 然后我们查看了cpu利用率,发现mongod实例只使用一个CPU(满分4个)来执行查询。我们现在计划在每台机器上安装4个分片来解决这个问题。如果你看到更好的方法,请告诉我。
还有一件事,我知道我的查询必须扫描整个集合但是2秒扫描~200MB数据对我来说似乎非常高。是期待还是我遗失了什么?
答案 0 :(得分:2)
我尝试的事情:
1)您以一种使分组变得非常困难的方式组织了您的数据。如果您按照以下方式组织文档,可能会获得更好的结果:
{
...
"actionType" : [{k:1, v:66}, {k:47, v:66}, {k:42, v:72}, {k:46, v:130}]
}
这将允许您在' actionType.k'上创建索引。然后,您可以对该索引进行匹配,以将整个数据集减少为您希望此聚合所需的确切actionTypes,其中您的查询为:
db.action.aggregate([{$unwind: '$actionType'},
{$group:{_id:'$actionType.k', t:{$sum:'$actionType.v'} } }]);
//output
{ "_id" : 46, "t" : 130 }
{ "_id" : 42, "t" : 72 }
{ "_id" : 47, "t" : 66 }
{ "_id" : 1, "t" : 66 }
然后在' actionType.k'上确保指数。如果您不打算过滤所有不同的键值,则索引将有很大帮助,具体取决于文档中键的密度。如果您计划对每个密钥求和,那么索引在这里不会有帮助。
2)在cron-job / setTimeout计划中映射减少和/或添加这些。同样,根据您的更新周期以及您在任何时候需要数据的准确程度,请设置如下内容:
如果你只对这个数据库进行插入操作,那么这是有效的。
3)如果键值正在定期更改(更新而不是插入),那么您可能会更好地运行与更新主集合同时发生的更改日志插入。
db.changes.insert({key:44, change:2});
db.changes.insert({key:34, change:-2});
然后经常清空变化'集合将值汇总到不同的集合。