【发布时间】:2015-04-10 06:25:06
【问题描述】:
我有一个 mongo 查询,它花费的时间与 java 代码和 shell 不同。 Java代码如下,
mongo服务器的版本是v2.6.5,v2.4.8版本没有问题。
DBObject obj = new BasicDBObject();
obj.put("accountId",accountId);
List<DBObject> listOr = new ArrayList<DBObject>();
listOr.add(new BasicDBObject("status", 11));
listOr.add(new BasicDBObject("status", 12));
obj.put("$or", listOr);
BasicDBObject andDB = new BasicDBObject();
andDB.append("$gt", 0);
andDB.append("$lt",4514185);
obj.put("currBoardId",andDB);
DBCursor cur = null;
cur = coll.find(obj,new BasicDBObject("currBoardId",1)).sort(new BasicDBObject("commentId",-1)).limit(10);
当我运行代码时,我可以从配置文件集合中获取慢查询记录。它显示“nscanned”:1566031 和“millis”:4724。
> db.system.profile.find().sort({$natural:-1}).limit(10);
{ "op" : "query", "ns" : "l_comment.comment", "query" : { "$query" : { "accountId" : NumberLong(4), "$or" : [ { "状态“:11 },{“状态”:12 }],“currBoardId”:{“$gt”:0,“$lt”:NumberLong(4514185)}},“$orderby”:{“commentId”:- 1 } },“cursorid”:220355902849,“ntoreturn”:10,“ntoskip”:0,“nscanned”:1566031,“nscannedObjects”:1566031,“keyUpdates”:0,“numYield”:5,“lockStats”: {“timeLockedMicros”:{“r”:NumberLong(8921271),“w”:NumberLong(0)},“timeAcquiringMicros”:{“r”:NumberLong(14),“w”:NumberLong(2)}}, “nreturned”:10,“responseLength”:410,“millis”:4724,“execStats”:{“type”:“PROJECTION”,“works”:1566031,“yields”:12234,“unyields”:12234,“无效”:0,“高级”:10,“needTime”:0,“needFetch”:0,“isEOF”:0,“children”:[{“type”:“FETCH”,“works”:1566031,“产量”:12234,“unyields”:12234,“无效”:0,“高级”:10,“needTime”:1566021,“needFetch”:0,“isEOF”: 0,“alreadyHasObj”:0,“forcedFetches”:0,“matchTested”:10,“children”:[{“type”:“IXSCAN”,“works”:1566031,“yields”:12234,“unyields”: 12234,“无效”:0,“高级”:1566031,“needTime”:0,“needFetch”:0,“isEOF”:0,“keyPattern”:“{ commentId:-1.0 }”,“isMultiKey”:0 ,“boundsVerbose”:“字段#0 ['commentId']:[MaxKey,MinKey]”,“yieldMovedCursor”:0,“dupsTested”:0,“dupsDropped”:0,“seenInvalidated”:0,“matchTested”: 0,“keysExamined”:1566031,“孩子”:[] }] } ]},“ts”:ISODate(“2015-02-10T08:51:16.195Z”),“客户”:“192.168.66.103”, “所有用户”:[],“用户”:“”}
但是当我从 shell 运行查询时,它返回很快。
db.comment.find({ "accountId" : NumberLong(4), "$or" : [ { "status" : 11 }, { "status" : 12 } ], "currBoardId" : { "$gt" : 0, "$lt" : NumberLong(4514185) }}).sort({commentId:-1}).limit(10)
下面是它的解释输出。它显示查询扫描 10517 条记录并使用 109 毫秒。 为什么会这样,我该如何改进代码?
感谢任何提示和帮助。
{
"clauses" : [
{
"cursor" : "BtreeCursor idx_atst",
"isMultiKey" : false,
"n" : 10,
"nscannedObjects" : 10517,
"nscanned" : 10517,
"scanAndOrder" : true,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"accountId" : [
[
NumberLong(4),
NumberLong(4)
]
],
"rootId" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"status" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"type" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
},
{
"cursor" : "BtreeCursor ",
"isMultiKey" : false,
"n" : 0,
"nscannedObjects" : 0,
"nscanned" : 0,
"scanAndOrder" : true,
"indexOnly" : false,
"nChunkSkips" : 0,
"indexBounds" : {
"accountId" : [
[
NumberLong(4),
NumberLong(4)
]
],
"rootId" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
],
"status" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"type" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
}
}
],
"cursor" : "QueryOptimizerCursor",
"n" : 10,
"nscannedObjects" : 10517,
"nscanned" : 10517,
"nscannedObjectsAllPlans" : 31574,
"nscannedAllPlans" : 31574,
"scanAndOrder" : false,
"nYields" : 246,
"nChunkSkips" : 0,
"millis" : 109,
"server" : "app-sz-2-3.sz.chosk.net:27017",
"filterSet" : false,
"stats" : {
"type" : "KEEP_MUTATIONS",
"works" : 10529,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 10,
"needTime" : 10519,
"needFetch" : 0,
"isEOF" : 0,
"children" : [
{
"type" : "OR",
"works" : 10529,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 10,
"needTime" : 10519,
"needFetch" : 0,
"isEOF" : 0,
"dupsTested" : 10,
"dupsDropped" : 0,
"locsForgotten" : 0,
"matchTested_0" : 0,
"matchTested_1" : 0,
"children" : [
{
"type" : "SORT",
"works" : 10529,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 10,
"needTime" : 10518,
"needFetch" : 0,
"isEOF" : 1,
"forcedFetches" : 0,
"memUsage" : 4675,
"memLimit" : 33554432,
"children" : [
{
"type" : "FETCH",
"works" : 10518,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 1909,
"needTime" : 8608,
"needFetch" : 0,
"isEOF" : 1,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 1909,
"children" : [
{
"type" : "IXSCAN",
"works" : 10518,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 10517,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 1,
"keyPattern" : "{ accountId: 1, rootId: -1.0, status: 1, type: 1 }",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['accountId']: [4, 4], field #1['rootId']: [MaxKey, MinKey], field #2['status']: [MinKey, MaxKey], field #3['type']: [MinKey, MaxKey]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 10517,
"children" : [ ]
}
]
}
]
},
{
"type" : "SORT",
"works" : 0,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 0,
"forcedFetches" : 0,
"memUsage" : 0,
"memLimit" : 33554432,
"children" : [
{
"type" : "FETCH",
"works" : 0,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 0,
"alreadyHasObj" : 0,
"forcedFetches" : 0,
"matchTested" : 0,
"children" : [
{
"type" : "IXSCAN",
"works" : 0,
"yields" : 246,
"unyields" : 246,
"invalidates" : 0,
"advanced" : 0,
"needTime" : 0,
"needFetch" : 0,
"isEOF" : 0,
"keyPattern" : "{}",
"isMultiKey" : 0,
"boundsVerbose" : "field #0['accountId']: [4, 4], field #1['rootId']: [MaxKey, MinKey], field #2['status']: [MinKey, MaxKey], field #3['type']: [MinKey, MaxKey]",
"yieldMovedCursor" : 0,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0,
"matchTested" : 0,
"keysExamined" : 0,
"children" : [ ]
}
]
}
]
}
]
}
]
}
}
【问题讨论】:
-
查询的不同之处在于,您在 Java 代码中使用
new BasicDBObject("currBoardId",1)限制返回的键,剥离结果应该需要一些时间,但不应更改扫描的对象。很有趣。 -
这让我很困惑
-
你能在java中显示变量
accountId的定义吗? -
所有参数都在慢查询记录中,我在shell中运行从那里复制的查询。
-
从 Java 运行的查询和从 shell 运行的查询使用了不同的索引。从 Java 运行的查询使用索引来处理排序
{ "commentId" : -1 },而从 shell 运行的查询使用索引来处理实际的查询谓词。这解释了为什么 Java 查询的nscanned比 shell 查询高得多。这种索引选择是否每次都会发生?还是 Java 查询仅在某些时候选择排序索引?你需要其他的排序索引吗?能否将排序字段添加到 shell 查询的索引中?
标签: mongodb