我有一个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);
当我运行代码时,我可以从配置文件集合中获取慢查询记录。它显示&#34; nscanned&#34; :1566031和&#34; millis&#34; :4724。
> db.system.profile.find().sort({$natural:-1}).limit(10);
{&#34; op&#34; :&#34;查询&#34;,&#34; ns&#34; :&#34; l_comment.comment&#34;,&#34;查询&#34; :{&#34; $ query&#34; :{&#34; accountId&#34; :NumberLong(4),&#34; $或&#34; :[{&#34; status&#34; :11},{&#34; status&#34; :12}],&#34; currBoardId&#34; :{&#34; $ gt&#34; :0,&#34; $ lt&#34; :NumberLong(4514185)}},&#34; $ orderby&#34; :{&#34; commentId&#34; :-1}},&#34; cursorid&#34; :220355902849,&#34; ntoreturn&#34; :10,&#34; ntoskip&#34; :0,&#34; nscanned&#34; :1566031,&#34; nscannedObjects&#34; :1566031,&#34; keyUpdates&#34; :0,&#34; numYield&#34; :5,&#34; lockStats&#34; :{&#34; timeLockedMicros&#34; :{&#34; r&#34; :NumberLong(8921271),&#34; w&#34; :NumberLong(0)},&#34; timeAcquiringMicros&#34; :{&#34; r&#34; :NumberLong(14),&#34; w&#34; :NumberLong(2)}},&#34; nreturned&#34; :10,&#34; responseLength&#34; :410,&#34; millis&#34; :4724,&#34; execStats&#34; :{&#34; type&#34; :&#34; PROJECTION&#34;,&#34;工作&#34; :1566031,&#34;收益率&#34; :12234,&#34; unyields&#34; :12234,&#34;无效&#34; :0,&#34;高级&#34; :10,&#34; needTime&#34; :0,&#34; needFetch&#34; :0,&#34; isEOF&#34; :0,&#34;孩子&#34; :[{&#34; type&#34; :&#34; FETCH&#34;,&#34;工作&#34; :1566031,&#34;收益率&#34; :12234,&#34; unyields&#34; :12234,&#34;无效&#34; :0,&#34;高级&#34; :10,&#34; needTime&#34; :1566021,&#34; needFetch&#34; :0,&#34; isEOF&#34; :0,&#34; alreadyHasObj&#34; :0,&#34; forcedFetches&#34; :0,&#34; matchTested&#34; :10,&#34;孩子&#34; :[{&#34; type&#34; :&#34; IXSCAN&#34;,&#34;工作&#34; :1566031,&#34;收益率&#34; :12234,&#34; unyields&#34; :12234,&#34;无效&#34; :0,&#34;高级&#34; :1566031,&#34; needTime&#34; :0,&#34; needFetch&#34; :0,&#34; isEOF&#34; :0,&#34; keyPattern&#34; :&#34; {commentId:-1.0}&#34;,&#34; isMultiKey&#34; :0,&#34; boundsVerbose&#34; :&#34;字段#0 [&#39; commentId&#39;]:[MaxKey,MinKey]&#34;,&#34; yieldMovedCursor&#34; :0,&#34; dupsTested&#34; :0,&#34; dupsDropped&#34; :0,&#34; seenInvalidated&#34; :0,&#34; matchTested&#34; :0,&#34; keysExamined&#34; :1566031,&#34;孩子&#34; :[]}]}]},&#34; ts&#34; :ISODate(&#34; 2015-02-10T08:51:16.195Z&#34;),&#34;客户&#34; :&#34; 192.168.66.103&#34;,&#34; allUsers&#34; :[],&#34;用户&#34; :&#34;&#34; }
但是当我从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" : [ ]
}
]
}
]
}
]
}
]
}
}
答案 0 :(得分:0)
在您的Shell查询中,您在NumberLong(4514185)
语句的$lt
中使用了$or
。但是在您的Java查询中,您正在使用andDB.append("$lt", 4514185);
这是Integer
,因此您的Java查询需要从Integer到Long的类型转换。尝试在您的号码后使用andDB.append("$lt", 4514185L);
和L
来创建带有Long的查询。 accountId
也应该是Long
。
答案 1 :(得分:0)
通过wdberkeley的暗示,我对指数给予了一些关注。我不明白mongodb是如何选择索引的,但是在我添加另一个索引后,java代码中的查询选择了正确的索引。即使我删除后来添加的索引,它仍然使用正确的索引。因此,如果查询没有使用我们想要的索引,我们应该使用提示来分配我们想要的索引。
我添加的索引:
ensureIndex({"accountId" : -1,"type" : 1,"status" : 1},{"name" : "idx_ats"});