为什么MongoDB的性能比MySQL慢?

时间:2014-12-19 14:08:27

标签: mongodb mongodb-query

我的系统配置: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 }

1 个答案:

答案 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查询。