mongodb没有使用索引

use*_*326 1 mongodb nosql

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

db.colaboradores.getIndexKeys()
[ { "_id" : 1 }, { "nome" : 1 }, { "sobrenome" : 1 } ]
Run Code Online (Sandbox Code Playgroud)

和查询一样

db.colaboradores.find({_id: ObjectId("5040e298914224dca3000006")}).explain();
Run Code Online (Sandbox Code Playgroud)

那与索引很好

{
    "cursor" : "BtreeCursor _id_",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
}
Run Code Online (Sandbox Code Playgroud)

但运行时:

db.colaboradores.find({nome: /^Administrador/}).explain()
Run Code Online (Sandbox Code Playgroud)

mongodb不再使用索引:

{
    "cursor" : "BtreeCursor nome_1",
    "nscanned" : 10000,
    "nscannedObjects" : 10000,
    "n" : 10000,
    "millis" : 25,
}
Run Code Online (Sandbox Code Playgroud)

任何解决方案 谢谢!

she*_*man 6

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

输出的解释:

"cursor" : "Btree_Cursor nome_1" 表示数据库使用“nome”的升序索引来满足查询。如果未使用索引,则光标将为“BasicCursor”。

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

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


Wil*_*m Z 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)
Run Code Online (Sandbox Code Playgroud)

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

find(b)
find(c)
find(b,c)
find(b,c).sort(a)
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @WilliamZ 很好的信息,但是从原始帖子中 `getIndexKey()` 的输出来看,他似乎已经在 `nome` 上有了一个单键索引(它显示了 3 个单独的单键索引,而不是一个复合索引)。 (2认同)