MongoDB:降低了查询性能

时间:2015-02-06 08:55:24

标签: mongodb query-performance

我在MongoDB中有一个用户集合,有超过250万条记录,构成30 GB。我有大约4到6 GB的索引。它位于带有两个分片的分片环境中,每个分片都包含副本集。服务器专门针对Mongo而没有开销。总RAM超过10 GB,足以满足我正在执行的查询类型(如下所示)。

我担心的是,尽管有适当字段的索引时间来检索结果是巨大的(2分钟到高达30分钟),这是不可接受的。我是MongoDB&的新手为什么会发生这种情况真的处于困惑状态。

示例架构是:

user:
{
_id: UUID (indexed by default),
name: string,
dob: ISODate,
addr: string,
createdAt: ISODate (indexed),
.
.
.,
transaction:[
{
firstTransaction: ISODate(indexed),
lastTransaction: ISODate(indexed),
amount: float,
product: string (indexed),
.
.
.
},...
],
other sub documents...
}

子文档长度从0到50左右不等。

我执行的查询是:

1)db.user.find().min({createdAt:ISODate("2014-12-01")}).max({createdAt:ISODate("2014-12-31")}).explain()

这个查询起初运行缓慢,但后来闪电般快(我猜是因为预热)。

2)db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).explain()

此查询耗时超过30分钟&每次演出都相同时,热身并没有帮助。它回收了超过一半的收藏。

3)db.user.find({transaction:{$elemMatch:{product:'mobile'}}, firstTransaction:{$in:[ISODate("2015-01-01"),ISODate("2015-01-02")]}}}}).explain()

这是我想要表现的主要查询。但运气不好,这个查询需要超过30分钟才能完成。我尝试了很多版本,例如:

db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).min({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-01")}}}).max({transaction:{$elemMatch:{firstTransaction:ISODate("2015-01-02")}}}).explain()

这个查询给了我错误:

  

planner返回错误:无法找到max / min的相关索引   查询&使用提示():

planner returned error: hint provided does not work with min query

我使用了min max函数,因为MongoDB中使用$ lt,$ gt运算符的范围查询的不确定性,有时会忽略绑定&运算符中的任何一个。最终扫描的文档超出了所需的数量。

我使用的索引如下:

db.user.ensureIndex({createdAt: 1})

db.user.ensureIndex({"transaction.firstTransaction":1})

db.user.ensureIndex({"transaction.lastTransaction":1})

db.user.ensureIndex({"transaction.product":1})

我尝试对3查询使用复合索引,即:

db.user.ensureIndex({"transaction.firstTransaction":1, "transaction.product":1})

但这似乎没有给我任何结果。查询卡住&永远不会返回结果。我是认真的。决不。像死锁一样。我不知道为什么。所以我放弃了这个指数&等了半个多小时后得到了结果(非常令人沮丧)。

请帮助我,因为我真的很想找到解决方案&没有想法。

此输出可能会有所帮助:

Following is the output for:

查询:

db.user.find({transaction:{$elemMatch:{product:"mobile", firstTransaction:{$gte:ISODate("2015-01-01"), $lt:ISODate("2015-01-02")}}}}).hint("transaction.firstTransaction_1_transaction.product_1").explain()

输出:

{
        "clusteredType" : "ParallelSort",
        "shards" : {
                "test0/mrs00.test.com:27017,mrs01.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
                                "isMultiKey" : true,
                                "n" : 622,
                                "nscannedObjects" : 350931,
                                "nscanned" : 352000,
                                "nscannedObjectsAllPlans" : 350931,
                                "nscannedAllPlans" : 352000,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 119503,
                                "nChunkSkips" : 0,
                                "millis" : 375693,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ],
                                        "transaction.firstTransaction" : [
                                                [
                                                        true,
                                                        ISODate("2015-01-02T00:00:00Z")
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-31:27017",
                                "filterSet" : false
                        }
                ],
                "test1/mrs10.test.com:27017,mrs11.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
                                "isMultiKey" : true,
                                "n" : 547,
                                "nscannedObjects" : 350984,
                                "nscanned" : 352028,
                                "nscannedObjectsAllPlans" : 350984,
                                "nscannedAllPlans" : 352028,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 132669,
                                "nChunkSkips" : 0,
                                "millis" : 891898,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ],
                                        "transaction.firstTransaction" : [
                                                [
                                                        true,
                                                        ISODate("2015-01-02T00:00:00Z")
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-34:27017",
                                "filterSet" : false
                        }
                ]
        },
        "cursor" : "BtreeCursor transaction.product_1_transaction.firstTransaction_1",
        "n" : 1169,
        "nChunkSkips" : 0,
        "nYields" : 252172,
        "nscanned" : 704028,
        "nscannedAllPlans" : 704028,
        "nscannedObjects" : 701915,
        "nscannedObjectsAllPlans" : 701915,
        "millisShardTotal" : 1267591,
        "millisShardAvg" : 633795,
        "numQueries" : 2,
        "numShards" : 2,
        "millis" : 891910
}

查询:

db.user.find({transaction:{$elemMatch:{product:'mobile'}}}).explain()

输出:

{
        "clusteredType" : "ParallelSort",
        "shards" : {
                "test0/mrs00.test.com:27017,mrs01.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1",
                                "isMultiKey" : true,
                                "n" : 553072,
                                "nscannedObjects" : 553072,
                                "nscanned" : 553072,
                                "nscannedObjectsAllPlans" : 553072,
                                "nscannedAllPlans" : 553072,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 164888,
                                "nChunkSkips" : 0,
                                "millis" : 337909,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-31:27017",
                                "filterSet" : false
                        }
                ],
                "test1/mrs10.test.com:27017,mrs11.test.com:27017" : [
                        {
                                "cursor" : "BtreeCursor transaction.product_1",
                                "isMultiKey" : true,
                                "n" : 554176,
                                "nscannedObjects" : 554176,
                                "nscanned" : 554176,
                                "nscannedObjectsAllPlans" : 554176,
                                "nscannedAllPlans" : 554176,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 107496,
                                "nChunkSkips" : 0,
                                "millis" : 327928,
                                "indexBounds" : {
                                        "transaction.product" : [
                                                [
                                                        "mobile",
                                                        "mobile"
                                                ]
                                        ]
                                },
                                "server" : "ip-12-0-0-34:27017",
                                "filterSet" : false
                        }
                ]
        },
        "cursor" : "BtreeCursor transaction.product_1",
        "n" : 1107248,
        "nChunkSkips" : 0,
        "nYields" : 272384,
        "nscanned" : 1107248,
        "nscannedAllPlans" : 1107248,
        "nscannedObjects" : 1107248,
        "nscannedObjectsAllPlans" : 1107248,
        "millisShardTotal" : 665837,
        "millisShardAvg" : 332918,
        "numQueries" : 2,
        "numShards" : 2,
        "millis" : 337952
}

如果我错过了任何细节,请告诉我。

感谢。

2 个答案:

答案 0 :(得分:3)

第1页:您的查询过于复杂。太经常使用$ elemMatch方式。 第二:如果您可以在查询中包含分片键,它将大大提高速度。

我将为您优化您的查询:

db.user.find({
     createdAt: {
          $gte: ISODate("2014-12-01"), 
          $lte: ISODate("2014-12-31")
     }
}).explain()

db.user.find({
    'transaction.product':'mobile'
}).explain()

db.user.find({
    'transaction.product':'mobile', 
    firstTransaction:{
       $in:[
           ISODate("2015-01-01"),
           ISODate("2015-01-02")
       ]
    }
}).explain()

底线是这样的:每次节省时间包括你的分片键。

甚至可以节省遍历分片键的时间并多次进行相同的查询。

答案 1 :(得分:0)

性能下降的原因是大型工作集。对于某些查询(主要是范围查询),该集合超出了物理限制&发生了页面错误。由于这种性能降低了。 我做的一个解决方案是为查询应用一些过滤器,这将限制结果集和&试图执行相等检查而不是范围(迭代范围)。 那些调整对我有用。希望它也能帮助别人。