2012-08-31 68 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索引,它掃描每一個單一的文件來查找匹配。 –