web-dev-qa-db-fra.com

MongoDB 'count ()' est très lent. Comment pouvons-nous peaufiner / contourner cela?

J'utilise actuellement MongoDB avec des millions d'enregistrements de données. J'ai découvert une chose assez ennuyeuse.

Lorsque j'utilise la fonction 'count ()' avec un petit nombre de collectes de données interrogées, c'est très rapide. Cependant, lorsque la collecte de données interrogée contient des milliers voire des millions d'enregistrements de données, l'ensemble du système devient très lent.

Je me suis assuré d'avoir indexé les champs obligatoires.

Quelqu'un a-t-il rencontré une chose identique? Comment faites-vous pour améliorer cela?

54
Winston Chen

Il existe désormais une autre optimisation que la création d'un index approprié.

db.users.ensureIndex({name:1});
db.users.find({name:"Andrei"}).count();

Si vous avez besoin de compteurs, je vous suggère de les précalculer chaque fois que cela est possible. En utilisant l'opération atomique $ inc et en n'utilisant pas du tout count({}).

Mais les gars de mongodb travaillent dur sur mongodb, donc, count({}) améliorations qu'ils envisagent dans mongodb 2.1 selon jira bug .

31
Andrew Orsich

Vous pouvez vous assurer que l'index est réellement utilisé sans accès au disque.

Disons que vous voulez compter les enregistrements avec le nom: "Andrei"

Vous assurez l'index sur le nom (comme vous l'avez fait) et

db.users.find({name:"andrei"}, {_id:0, name:1}).count()

vous pouvez vérifier que c'est le moyen le plus rapide de compter (sauf avec le pré-calcul) en vérifiant si

db.users.find({name:"andrei"}, {_id:0, name:1}).explain() 

affiche un champ index_only défini sur true.

Cette astuce garantira que votre requête ne récupérera les enregistrements que du ram (index) et non du disque.

10
kamaradclimber

Pour moi, la solution était de changer l'index en clairsemé. Cela dépend de la situation spécifique, essayez-le si vous le pouvez.

db.Account.createIndex( { "date_checked_1": 1 }, { sparse: true } )

db.Account.find({    
     "dateChecked" : { $exists : true }    
}).count()

318 milliers d'enregistrements dans la collection

  • 0,31 sec - avec index clairsemé
  • 0,79 s - avec index non clairsemé
7
Vaclav Kohout

Vous n'avez pratiquement pas de chance pour l'instant, compter dans mongodb est horrible et ne s'améliorera pas dans un avenir proche. Voir: https://jira.mongodb.org/browse/SERVER-1752

Par expérience, vous ne devriez presque jamais l'utiliser à moins que ce soit une chose ponctuelle, quelque chose qui se produit très rarement ou que votre base de données soit assez petite.

Comme l'a déclaré @Andrew Orsich, utilisez des compteurs dans la mesure du possible (la chute des compteurs est le verrouillage d'écriture global, mais mieux que count () malgré tout).

5
Travis Reeder