mongodb没有使用索引

时间:2012-08-31 17:18:41

标签: mongodb nosql

我有一个包含这些索引的集合:

db.colaboradores.getIndexKeys()
[ { "_id" : 1 }, { "nome" : 1 }, { "sobrenome" : 1 } ]

和像

这样的查询
db.colaboradores.find({_id: ObjectId("5040e298914224dca3000006")}).explain();

使用索引

完成工作
{
    "cursor" : "BtreeCursor _id_",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
}

但运行时:

db.colaboradores.find({nome: /^Administrador/}).explain()

mongodb不再使用索引:

{
    "cursor" : "BtreeCursor nome_1",
    "nscanned" : 10000,
    "nscannedObjects" : 10000,
    "n" : 10000,
    "millis" : 25,
}

任何解决方案? 谢谢!

2 个答案:

答案 0 :(得分:6)

您希望从MongoDB看到您所看到的行为。对于使用复合索引的任何查询(包含多个字段的查询),这通常是正确的。

经验法则是:

如果您在{a:1,b:1,c:1}上有索引,那么以下查询将能够有效地使用该索引:

find(a)
find(a,b)
find(a,b,c)
find(a).sort(a)
find(a).sort(b)
find(a,b).sort(b)
find(a,b).sort(c)

但是,以下查询将无法充分利用索引:

find(b)
find(c)
find(b,c)
find(b,c).sort(a)

原因是MongoDB创建复合索引的方式。索引是btree,并且节点按排序顺序出现在btree中,最左边的字段是主要排序,下一个字段是次要排序,依此类推。

如果跳过索引的主要成员,那么索引遍历将不得不跳过大量的块。如果性能很慢,那么查询优化器将选择使用完整集合扫描而不是使用索引。

有关MongoDB索引的更多信息,请参阅此处的优秀文章:

答案 1 :(得分:4)

它确实使用了一个索引 - 你可以判断,因为游标是一个BtreeCursor。您的收藏中有很多(10000)文件,其中包括“无名”文件。等于' Administrador'。

输出的解释:

"光标" :" Btree_Cursor nome_1"表示数据库在" nome"上使用了升序索引。满足查询。如果没有使用索引,则光标将是" BasicCursor"。

" nscanned" :数据库必须检查的文档数量(" nscannedObjects"对于此查询基本相同)

" N" :返回的文档数。这与" nscanned"相同的事实意味着索引是有效的 - 它不必检查任何与查询不匹配的文档。