2014-01-15 125 views
0

我已经到位以下蒙戈测试集群MongoDB的慢查询性能

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

我有大约4100万条记录在整个碎片中分割,我定义了一个复合索引{field1:1,field2:1,field3:1},我的查询是(x和y之间的字段= 1和字段2),我预计复合索引对于这些查询很有用,但查询响应时间大约为8秒,对于我描述的查询。当我执行查找时,我只指定了感兴趣的字段。

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" : "[email protected]", 
    "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。感谢任何帮助。

+2

请运行'你的查询explain'和结果添加到您的文章 –

+2

看来,查询计划会扫描索引LOGIN_ID每个值,共有将近180万登录记录。你可以添加你的查询和一个示例文档。另外,您使用的是哪个版本的MongoDB? –

+0

此查询返回多少个文档?如果它提取的文档太多,请尝试'limit' –

回答

0

我看到了下面的点可能一头扎进找到更多确切的问题:

  1. 什么是login_time又是什么在查询范围的数字到底意味着什么?数值差异使得该范围看起来相当宽。可能是你过滤的标准是多么广泛?这也是来自解释计划的“已扫描”的指示。

  2. 我看到索引是在login_time和login_id上,其中您的查询在login_time和login_type上。尽管您使用的是索引,但是您的查询条件足够宽以涵盖更大的索引范围,并且由于login_type的第二条件不是索引的一部分,查询将需要获取所有“已扫描”文档以确定如果它是这个查询的有效记录。