7

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

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,
}

任何解决方案?谢谢!

4

2 回答 2

16

您看到的行为是 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 索引的更多信息,请在此处查看这篇出色的文章:

于 2012-08-31T17:55:37.350 回答
4

它确实使用了索引——你可以知道,因为光标是 BtreeCursor。您的集合中有很多 (10000) 个文档,其中“nome”等于“Administrador”。

输出说明:

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

“nscanned”:数据库必须检查的文档数量(“nscannedObjects”对于这个查询基本上是一样的)

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

于 2012-08-31T17:25:34.783 回答