2012-08-31 69 views
1

我与这些指标的集合:MongoDB中不使用索引

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

和像

db.colaboradores.find({_id: ObjectId("5040e298914224dca3000006")}).explain(); 

thatworks罚款指标

{ 
    "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

您看到的行为预计来自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的创建复合索引的方式。索引是b树,节点以排序顺序存在于树中,最左边的字段是主要类,下一个字段是次要类,等等。

如果您跳过索引的主要成员,那么索引遍历将不得不跳过很多块。如果性能较差,那么查询优化器将选择使用全集合扫描而不是使用索引。

有关MongoDB的索引的详细信息,请参见这里这个优秀的文章:

+0

威廉,那么正确的方法是什么?感谢文章。 – user1639326

+0

如果你打算在'nome'上进行查询,你需要有一个额外的索引,'nome'是索引中的第一个元素。 –

+0

@WilliamZ好信息,但是从原始帖子中的getIndexKey()的输出来看,他已经有了'nome'上的单键索引(它显示了3个独立的单键索引,而不是一个复合索引) 。 – JohnnyHK

3

它确实使用了一个索引 - 因为游标是一个BtreeCursor,所以可以说明。您的集合中有大量(10000)个文档,其中'nome'等于'Administrador'。

输出的解释:

“光标”:“Btree_Cursor nome_1”是指该数据库中使用的升序索引的“诺姆”满足查询。如果没有使用索引,则光标将是“BasicCursor”。

“nscanned”:的数据库必须要检查的文档数(“nscannedObjects”基本上是为这个查询同样的事情)

“N”:文件的数量返回。这与“已扫描”相同的事实意味着索引是有效的 - 它不必检查任何与查询不匹配的文档。

+0

不使用: { “光标”: “BtreeCursor nome_1”, “nscanned”: 10000, “nscannedObjects”:10000, “n”:10000, “millis”:25, } – user1639326

+0

它使用默认的_id索引,它扫描每一个单一的文件来查找匹配。 –