2012-08-31 7 views
1

J'ai une collection avec ces indices:mongodb ne pas utiliser les index

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

et une requête comme

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

thatworks fines avec index

{ 
    "cursor" : "BtreeCursor _id_", 
    "nscanned" : 0, 
    "nscannedObjects" : 0, 
    "n" : 0, 
    "millis" : 0, 
} 

mais lorsqu'il est exécuté:

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

mongodb ne pas utiliser les index plus: une

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

des solutions? Merci!

Répondre

4

Le comportement que vous voyez est attendu de MongoDB. Cela est généralement vrai pour toute requête où vous utilisez un index composé - un avec plusieurs champs.

Les règles de base sont les suivantes:

Si vous avez un index sur {a: 1, b: 1, c: 1}, puis les requêtes suivantes seront en mesure d'utiliser l'index efficace:

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) 

Cependant, les requêtes suivantes ne seront pas en mesure de tirer le meilleur parti de l'indice:

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

la raison est la façon dont MongoDB crée des index composés. Les index sont des btrees, et les nœuds sont présents dans le btree dans un ordre trié, le champ le plus à gauche étant le tri principal, le champ suivant étant le tri secondaire, et ainsi de suite.

Si vous ignorez le membre principal de l'index, la traversée d'index devra ignorer beaucoup de blocs. Si cette performance est lente, l'optimiseur de requête choisira d'utiliser une analyse de collection complète plutôt que d'utiliser l'index.

Pour plus d'informations sur les index MongoDB, voir cet excellent article ici:

+0

William, quelle est la bonne façon alors? Merci pour l'article. – user1639326

+0

Si vous allez faire des requêtes sur 'nome', vous avez besoin d'un index supplémentaire où 'nome' est le premier élément de l'index. –

+0

@WilliamZ Bonne info, mais à partir de la sortie de 'getIndexKey()' dans le message d'origine, il semble qu'il possède déjà un index à clé unique sur 'nome' (il montre 3 index séparés, pas un index composé) . – JohnnyHK

3

Il a utilisé un index - vous pouvez le dire car le curseur était un BtreeCursor. Vous avez beaucoup (10000) de documents dans votre collection où 'nome' est égal à 'Administrador'.

Une explication de la sortie:

« curseur »: « Btree_Cursor nome_1 » signifie que la base de données utilisé un index ascendant sur « nome » pour satisfaire la requête. Si aucun index n'était utilisé, le curseur serait "BasicCursor".

« nscanned »: Le nombre de documents que la base de données a dû vérifier (« nscannedObjects » est fondamentalement la même chose pour cette requête)

« n »: Le nombre de documents retournés. Le fait que cela soit identique à "nscanned" signifie que l'index est efficace - il n'a pas eu à vérifier les documents qui ne correspondaient pas à la requête.

+0

Ne pas utiliser: { "curseur": "BtreeCursor nome_1", "nscanned": 10000, "nscannedObjects": 10000, "n": 10000, "millis": 25, } – user1639326

+0

Il utilisait le _id par défaut index et il a scanné chaque document pour trouver des correspondances. –