3 votes

MongoDB optimise FindAndModify ou Find + Sort

En utilisant MongoDB, j'essaie de mettre en file d'attente une recherche de clé à trois colonnes (a,b,c) avec un rang de priorité (d). J'ai une requête comme (syntaxe pymongo) :

collection.find({'a':'foo','b':'bar','c':'baz'}, sort = [('d', -1)] )

Avec un index composé (a+1,b+1,c+1,d-1), l'exécution d'un explain montre un balayage complet de la table et un BasicCursor.

Avec un seul index sur d, explain montre que l'index d seul est utilisé.

Pour une grande table, ce que je veux vraiment, c'est utiliser l'index composé. Comment puis-je faire en sorte que cela fonctionne ?

INDEX_INFORMATION : {u' id ' : {u'key' : [(u'_id', 1)], u'v' : 1}, u'color_1_level_1_in_progress_1_Ranking_-1': {u'key' : [(u'color', 1), (u'niveau', 1), (u'in_progress', 1), (u'Ranking', -1)], u'v' : 1}}

EXPLAIN ON A FIND+SORT QUERY
db.coll.find({'level' : {'$in' : [0,1,2]}, 'in_progress' : 0, 'color' : {'$in' : ['Red', 'Blue', 'Green]} },  sort = [('Ranking', -1)] ).explain()

OUTPUT ON EXPLAIN
OperationFailure: database error: too much data for sort() with no index.  add an index or specify a smaller limit

THE QUEUEING QUERY I CARE ABOUT OPTIMIZING
coll.find_and_modify(
  query = {'level' : {'$in' : [0,1,2]}, 'in_progress' : 0, 'color' : {'$in' : ['Red', 'Blue', 'Green']} },
  sort = {'Ranking' : -1},                                                                                                                                                                             
  update = {'$set': {'in_progress': 1}} 
)   

Notez que lorsque j'ajoute un index sur le champ de tri 'Ranking', l'explication indique que l'index Ranking est utilisé. Mais l'index composé n'est jamais utilisé et les performances sont très lentes sur un corpus de test de 1,5 millions de documents.

2voto

Rostyslav Dzinko Points 10667

Il existe un moyen de forcer l'utilisation d'un index spécifique lors d'une requête, appelé hint .

Il suffit de l'appeler sur un curseur :

cursor = collection.find({query-doc}).hint({index-fields})

1voto

kamaradclimber Points 1337

Le système d'indexation de Mongodb est basé sur l'expérimentation. Fondamentalement, l'optimiseur de requêtes exécutera vos requêtes en utilisant tous les index possibles et comparera le temps pour chacun. Il apprendra à utiliser le meilleur index pour un type de requête donné. D'après les documents sur optimiseur de requêtes :

Lors du test de nouveaux plans, MongoDB exécute plusieurs plans de requêtes en parallèle. Dès que l'un d'entre eux se termine, il met fin aux autres exécutions, et le système a appris quel plan est bon

Si votre collection est assez petite, il est possible que l'index choisi par l'optimiseur de requêtes ne soit pas celui que vous pensez être le meilleur. Cependant, il est le plus rapide pour cette requête et cette collection. Lorsque votre collection s'agrandira, un autre index sera peut-être mieux adapté.

Dans votre cas, je pense qu'il est plus facile pour mongo de scanner tous les documents puis de les trier avec l'index sur d car vous avez très peu de documents.

Essayez d'exécuter la même requête (plusieurs fois pour rendre l'apprentissage efficace) sur une collection contenant plus de documents (disons 1 million), vous verrez probablement qu'elle utilisera l'index complet.

Ainsi, l'utilisation de l'indice oe ne sera pas nécessaire (elle ne nuira pas pour autant). Mon conseil : laissez l'optimiseur de requêtes Mongo faire son travail :-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X