Mongod - IndexOnly为false,即使查询和投影都包含在索引中

时间:2013-09-11 05:36:09

标签: mongodb indexing

涵盖查询的mongo文档here讨论了查询和投影,如果您想要覆盖查询,只需关闭投影中的_id字段即可。如果你需要_id字段但仍然想要覆盖查询的效率(indexOnly = True)怎么办?

 db.collection.ensureIndex({field1:1,_id:1})
 db.collection.getIndexKeys()

 [{
    "_id" : 1
},
{
    "field1" : 1
},
{
    "field1" : 1,
    "_id" : 1
}]

db.collection.find({field1:{$regex:/^\s/}},{field1:1,_id:1}).explain()
{
"cursor" : "BtreeCursor fieldname",
"isMultiKey" : false,
"n" : 3582,
"nscannedObjects" : 3582,
"nscanned" : 130511408,
"nscannedObjectsAllPlans" : 3582,
"nscannedAllPlans" : 130511408,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 20,
"nChunkSkips" : 0,
"millis" : 158705,
"indexBounds" : {
    "cdr3_aa" : [
        [
            "",
            {

            }
        ]
    ]
},
"server" : localhost}

当然,如果我在投影上关闭_id,IndexOnly会返回true并且查询速度很快。我做错了什么?

编辑 - 我通过消除空格上的不区分大小写来提高效率,添加^来加速查询,但IndexOnly:False。我不明白为什么它不正确。

2 个答案:

答案 0 :(得分:1)

来自documentation

  

$ regex只能在正则表达式时有效地使用索引   有一个锚的开头(即^)的字符串,是一个   区分大小写的匹配。此外,虽然/^a /,/^a.*//^a.*$/匹配等效   字符串,它们具有不同的性能特征。所有这些表达都使用了   index是否存在适当的索引;但是,/^a.*//^a.*$/速度较慢。 /^a/可以   匹配前缀后停止扫描。

在您的情况下,您使用带有i的正则表达式,这意味着不区分大小写。因此,您应该从正则表达式中删除i并开始从字段的开头搜索。

顺便说一句,我没有指出你的搜索条件:在字段中查找一个空格字符\s,不区分大小写?

答案 1 :(得分:0)

不太确定原因,但似乎您的查询使用{ field1: 1 }索引而不是{ field1: 1, _id: 1 }索引。您可以尝试使用提示运行查询吗?

db.collection.find( { field1: {$regex:/^\s/} }, { field1: 1, _id: 1 } ).hint( { field1: 1, _id: 1 } ).explain()

可能是查询优化器最初选择了{field1:1}索引,并且没有重新评估各种计划。有关查询优化器的说明以及如何选择计划,请参阅http://docs.mongodb.org/manual/core/query-plans/