我的系统配置:OSx RAM:-8GB,2.5 Gz i5
两个数据库表都有1个行和相同的数据。我在两个数据库执行相同的聚合查询。
db.temp.aggregate([
{ "$match": { ITEMTYPE: 'like' } },
{ "$group" : {_id :{ cust_id2: "$ActorID", cust_id: "$ITEMTYPE"}, numberofActorID : {"$sum" : 1}}},
{ "$sort": { numberofActorID: -1 } },
{ "$limit" : 5 }
]);
我创建了覆盖索引
db.temp.ensureIndex( { "ITEMTYPE": 1, "ActorID": 1 } );
和"的选择性和#34;是80%
时间结果
sqlWithout sqlWithIndex mongoWithout mongoWithIndex
958 644 3043 4243
我没有升级MongoDB的系统参数(甚至没有分片) 请建议我为什么mongoDB很慢以及如何改善这个问题。
{
"stages" : [
{
"$cursor" : {
"query" : {
"ITEMTYPE" : "like"
},
"fields" : {
"ActorID" : 1,
"ITEMTYPE" : 1,
"_id" : 0
},
"plan" : {
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"scanAndOrder" : false,
"indexBounds" : {
"ITEMTYPE" : [
[
"like",
"like"
]
],
"ActorID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"allPlans" : [
{
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"scanAndOrder" : false,
"indexBounds" : {
"ITEMTYPE" : [
[
"like",
"like"
]
],
"ActorID" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
}
]
}
}
},
{
"$group" : {
"_id" : {
"cust_id2" : "$ActorID",
"cust_id" : "$ITEMTYPE"
},
"numberofActorID" : {
"$sum" : {
"$const" : 1
}
}
}
},
{
"$sort" : {
"sortKey" : {
"numberofActorID" : -1
},
"limit" : NumberLong(5)
}
}
],
"ok" : 1
}
JSON的结构
{ "_id" : ObjectId("5492ba51ff16cd9391a2c02d"), "POSTDBID" : 231041, "ITEMID" : 231041, "ITEMTYPE" : "post", "ITEMCREATIONDATE" : ISODate("2009-02-28T20:37:02Z"), "POSVal" : 0.327282, "NEGVal" : 0.315738, "NEUVal" : 0.356981, "LabelSentiment" : "Neutral", "ActorID" : NumberLong(1179444542), "QuarterLabel" : "2009-1\r", "rowid" : 2 }
答案 0 :(得分:2)
注意:为了这个答案,我提到的一些事情已经简化了。但是,据我所知,它们可以按照描述应用。
首先:聚合无法利用覆盖的查询:
即使管道使用索引,聚合仍然需要访问实际文档;即索引不能完全覆盖聚合管道。
(有关详细信息,请参阅Aggregation documentation。)
第二:聚合不意味着用作实时查询
聚合管道提供了map-reduce的替代方案,可能是聚合任务的首选解决方案,其中map-reduce的复杂性可能是无根据的。
你不想使用map / reduce进行实时处理,不是吗? ;)虽然有时聚合可以如此之快以至于它们可以用作实时查询,但它不是预期的目的。如果愿意,汇总用于预先计算统计数据。
您可能希望在匹配后立即使用$project
阶段,以将传递到组阶段的数据减少到在那里处理的数据:
{ $project: { 'ActorID':1, 'ITEMTYPE':1 } }
这可能会改善处理。
至于你的描述,我假设你使用某种MacBook。 OSX和你运行的程序需要相当多的RAM。另一方面,MongoDB试图在RAM中保留尽可能多的索引和所谓的工作集(最近访问的文档,以保持简单)。它就是这样设计的。它应该在一个或多个专用实例上运行。您可能希望使用MMS来检查是否存在大量页面错误 - 这是我所期望的。 MySQL更加保守,更少依赖于自由RAM,虽然当有一定数量的资源可用时,它会超越MongoDB(从概念上讲,因为两个DBMS 很难难以合理比较),因为当很多的RAM可用时,它没有针对处理情况进行优化。我们甚至没有触及各种流程之间的资源竞争,这也是MongoDB的已知性能杀手。
其次,万一你有旋转磁盘:由于各种原因,MongoDB在旋转磁盘上具有低于标准的读取性能,主要问题是寻找延迟。通常,MacBooks中的磁盘执行5400rpm,这进一步增加了寻道延迟,使问题恶化,并使其成为聚合的真正痛苦,如图所示 - 访问大量文档。 MongoDB存储引擎的工作方式,索引中相互跟随的两个文档可能会保存在两个完全不同的位置,即使在不同的数据文件中也是如此。 (这是因为MongoDB大量写入优化,因此文档在第一个位置写入,为文档提供足够的空间并填充。)因此,根据集合中的文档数量,您可以很多 of disk seek。
另一方面,MySQL更优化了读取。您没有向我们展示您的数据模型,但有时模型中的微小变化会对性能产生巨大影响。我建议对数据模型进行同行评审。
您正在比较两个DBMS,这两个DBMS是针对直径使用案例而设计和优化的环境,这个环境与其中一个系统是在未优化的用例中专门设计的相反,期待一个不是为此而做的工具的实时结果。这可能是MongoDB的表现优于MySQL的原因。附注:您没有向我们显示相应的(My)SQL查询。