【问题标题】:mongodb slow query performancemongodb慢查询性能
【发布时间】:2014-01-30 01:43:10
【问题描述】:

我有以下 mongo 测试集群

  1. 分片数 -2
  2. 没有配置服务器-1
  3. mongos 实例 -2
  4. 复制未启用

我有大约 4100 万条记录分布在各个分片中,我定义了一个复合索引 {field1:1,field2:1,field3:1},我的查询格式为 (field=1 and field2 between x and y ),我希望复合索引对这些查询有用,但是对于我描述的查询,查询响应时间约为 8 秒。我在执行 find 时只指定感兴趣的字段。

Mongos 安装在我执行查询的机器上,我正在使用 java 进行查询。

有人能解释一下可能的原因吗,为什么这个查询需要这么长时间?如果需要,我很乐意提供更多信息。

以下是解释命令的输出

{
    "indexBounds": {
        "LOGIN_ID": [
            [
                {
                    "$minElement": 1
                }, 
                {
                    "$maxElement": 1
                }
            ]
        ], 
        "LOGIN_TIME": [
            [
                1262332800000, 
                1293782400000
            ]
        ]
    }, 
    "nYields": 7, 
    "millisShardTotal": 7410, 
    "millisShardAvg": 7410, 
    "numQueries": 1, 
    "nChunkSkips": 0, 
    "shards": {
        "server1:27017": [
            {
                "nYields": 7, 
                "nscannedAllPlans": 1769804, 
                "allPlans": [
                    {
                        "cursor": "BtreeCursor LOGIN_TIME_1_LOGIN_ID_1", 
                        "indexBounds": {
                            "LOGIN_ID": [
                                [
                                    {
                                        "$minElement": 1
                                    }, 
                                    {
                                        "$maxElement": 1
                                    }
                                ]
                            ], 
                            "LOGIN_TIME": [
                                [
                                    1262332800000, 
                                    1293782400000
                                ]
                            ]
                        }, 
                        "nscannedObjects": 1763903, 
                        "nscanned": 1763903, 
                        "n": 14081
                    }, 
                    {
                        "cursor": "BasicCursor", 
                        "indexBounds": {}, 
                        "nscannedObjects": 5901, 
                        "nscanned": 5901, 
                        "n": 0
                    }
                ], 
                "millis": 7410, 
                "nChunkSkips": 0, 
                "server": "server2:27017", 
                "n": 14081, 
                "cursor": "BtreeCursor LOGIN_TIME_1_LOGIN_ID_1", 
                "oldPlan": {
                    "cursor": "BtreeCursor LOGIN_TIME_1_LOGIN_ID_1", 
                    "indexBounds": {
                        "LOGIN_ID": [
                            [
                                {
                                    "$minElement": 1
                                }, 
                                {
                                    "$maxElement": 1
                                }
                            ]
                        ], 
                        "LOGIN_TIME": [
                            [
                                1262332800000, 
                                1293782400000
                            ]
                        ]
                    }
                }, 
                "scanAndOrder": false, 
                "indexBounds": {
                    "LOGIN_ID": [
                        [
                            {
                                "$minElement": 1
                            }, 
                            {
                                "$maxElement": 1
                            }
                        ]
                    ], 
                    "LOGIN_TIME": [
                        [
                            1262332800000, 
                            1293782400000
                        ]
                    ]
                }, 
                "nscannedObjectsAllPlans": 1769804, 
                "isMultiKey": false, 
                "indexOnly": false, 
                "nscanned": 1763903, 
                "nscannedObjects": 1763903
            }
        ]
    }, 
    "n": 14081, 
    "cursor": "BtreeCursor LOGIN_TIME_1_LOGIN_ID_1", 
    "oldPlan": {
        "cursor": "BtreeCursor LOGIN_TIME_1_LOGIN_ID_1", 
        "indexBounds": {
            "LOGIN_ID": [
                [
                    {
                        "$minElement": 1
                    }, 
                    {
                        "$maxElement": 1
                    }
                ]
            ], 
            "LOGIN_TIME": [
                [
                    1262332800000, 
                    1293782400000
                ]
            ]
        }
    }, 
    "numShards": 1, 
    "clusteredType": "ParallelSort", 
    "nscannedAllPlans": 1769804, 
    "nscannedObjectsAllPlans": 1769804, 
    "millis": 7438, 
    "nscanned": 1763903, 
    "nscannedObjects": 1763903
}

我的数据库中的示例文档如下

    {
    "_id" : ObjectId("52d5192c1a45f84e48c24e2f"),
    "LOGIN_ID" : <loginId>,
    "LOGIN_TIME" : NumberLong("1372343932000"),
    "BUSINESS_ID" : <businessId>,
    "USER_ID" : <userid>,
    "EMAIL" : "a@b.com",
    "SITE_POD_NAME" : "x",
    "USER_AGENT" : "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML. like      Gecko) Chrome/26.0.1410.43 Safari/537.31"
    }

上面的文档中还有一些其他字段我不能暴露在外面,但它是字符串和字符串的简单键值

这就是我查询数据库的方式

    DBObject dbObject = new BasicDBObject("BUSINESS_ID", businessId)
        .append("LOGIN_TIME",
new BasicDBObject("$gte",start).append("$lt", end))
    .append("LOGIN_TYPE", loginType);

    long startTime = System.currentTimeMillis();
    DBObject keys = new BasicDBObject("LOGIN_TIME", 1);
DBCursor find = collection.find(dbObject, keys);

int count = 0;
while (find.hasNext()) {
    find.next();
    count++;
}
long endTime = System.currentTimeMillis();

Mongo DB 版本是 2.4.9。感谢任何帮助。

【问题讨论】:

  • 请运行explain的查询,并将结果添加到您的帖子中
  • 查询计划似乎扫描了索引中LOGIN_ID的每一个值,总共差不多180万条登录记录。您能否添加您的查询和示例文档。另外,您使用的是哪个版本的 MongoDB?
  • 这个查询返回多少个文档?如果它获取的文档太多,请尝试limit
  • 您好,这个查询返回大约14000个文档,但我只是指定要返回的LOGIN_TIME,所以返回的文档大小应该不会太大

标签: mongodb


【解决方案1】:

我看到以下地点可以找到更多关于确切问题的信息:

  1. 什么是 login_time 以及查询范围内的数字实际上是什么意思?通过数值差异,该范围看起来很宽。可能是您的过滤条件非常广泛?这也是解释计划中的“nscanned”的指示。

  2. 我看到索引位于 login_time 和 login_id,而您的查询位于 login_time 和 login_type。只是强调一下,尽管您正在使用索引,但您的查询条件足够宽,可以覆盖更大的索引范围,并且由于 login_type 的第二个条件不是索引的一部分,查询需要获取所有“nscanned”文档来确定如果它是此查询的有效记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 2022-01-04
    • 2021-09-26
    相关资源
    最近更新 更多