我坚持使用这个简单的前缀查询。虽然Mongo docs表示使用前缀regex格式(/ ^ a /)可以获得相当不错的性能,但是当我尝试对结果进行排序时,查询速度非常慢:
940毫秒
db.posts.find({hashtags:/ ^ noticias /})。limit(15).sort({rank:-1})。hint('hashtags_1_rank_-1')。explain()
{
"cursor" : "BtreeCursor hashtags_1_rank_-1 multi",
"isMultiKey" : true,
"n" : 15,
"nscannedObjects" : 142691,
"nscanned" : 142692,
"nscannedObjectsAllPlans" : 142691,
"nscannedAllPlans" : 142692,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 934,
"indexBounds" : {
"hashtags" : [
[
"noticias",
"noticiat"
],
[
/^noticias/,
/^noticias/
]
],
"rank" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "XRTZ048.local:27017"
}
但是,同一查询的未排序版本速度非常快:
0毫秒
db.posts.find({hashtags:/ ^ noticias /})。limit(15).hint('hashtags_1_rank_-1')。explain()
{
"cursor" : "BtreeCursor hashtags_1_rank_-1 multi",
"isMultiKey" : true,
"n" : 15,
"nscannedObjects" : 15,
"nscanned" : 15,
"nscannedObjectsAllPlans" : 15,
"nscannedAllPlans" : 15,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"hashtags" : [
[
"noticias",
"noticiat"
],
[
/^noticias/,
/^noticias/
]
],
"rank" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "XRTZ048.local:27017"
}
如果我删除正则表达式并排序,查询也很快:
0毫秒
db.posts.find({hashtags:'noticias'})。limit(15).sort({rank:-1})。hint('hashtags_1_rank_-1')。explain()
{
"cursor" : "BtreeCursor hashtags_1_rank_-1",
"isMultiKey" : true,
"n" : 15,
"nscannedObjects" : 15,
"nscanned" : 15,
"nscannedObjectsAllPlans" : 15,
"nscannedAllPlans" : 15,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"hashtags" : [
[
"noticias",
"noticias"
]
],
"rank" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "XRTZ048.local:27017"
}
似乎使用正则表达式和排序使Mongo扫描大量记录。但是,如果我不使用正则表达式,sort只扫描15。这有什么不对?
答案 0 :(得分:6)
explain输出中的scanAndOrder: true
表示查询必须检索文档,然后在返回输出之前在内存中对它们进行排序。这是一项昂贵的操作,会对查询的性能产生影响。
解释输出中scanAndOrder: true
的存在以及nscanned
和n
的差异表明查询未使用最佳索引。在这种情况下,它似乎需要进行收集扫描。您可以通过在sort
条件中包含索引键来缓解此问题。从我的测试:
db.posts.find({hashtags: /^noticias/ }).limit(15).sort({hashtags:1, rank : -1}).explain()
不需要扫描和订单,并返回您要查找的记录数量的n
和nscanned
。这也意味着对hashtags
键进行排序,这可能对您有用,也可能没有用,但应该提高查询的性能。