En utilisant le code:
all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()
print all_reviews[0]
print all_reviews[2000000]
Le compte imprime 2043484
, et il imprime all_reviews[0]
.
Cependant lors de l'impression all_reviews[2000000]
, Je reçois l'erreur:
pymongo.errors.OperationFailure: erreur de base de données: erreur du coureur: l'étape de tri de débordement, l'utilisation des données en mémoire tampon de 33554495 octets dépasse la limite interne de 33554432 octets
Comment puis-je gérer cela?
Vous rencontrez une limite de 32 Mo pour un tri en mémoire:
https://docs.mongodb.com/manual/reference/limits/#Sort-Operations
Ajoutez un index au champ de tri. Cela permet à MongoDB de vous envoyer des documents dans un ordre de tri, au lieu d'essayer de tous les charger en mémoire sur le serveur et de les trier en mémoire avant de les envoyer au client.
Comme dit par kumar_harsh
dans la section commentaires, je voudrais ajouter un autre point.
Vous pouvez afficher l'utilisation actuelle du tampon à l'aide de la commande ci-dessous sur la base de données admin
:
> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }
Il a une valeur par défaut de 2 Mo (33554432 octets). Dans ce cas, vous manquez de données de mémoire tampon afin de pouvoir augmenter la limite de mémoire tampon avec votre propre valeur optimale définie, par exemple 50 Mo, comme ci-dessous:
> db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }
Nous pouvons également définir cette limite de manière permanente par le paramètre ci-dessous dans le fichier de configuration mongodb:
setParameter=internalQueryExecMaxBlockingSortBytes=309715200
J'espère que cela t'aides !!!
Note
: Cette commande ne prend en charge qu'après la version 3.0 +
résolu avec indexation
db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])
Si vous voulez éviter de créer un index (par exemple, vous voulez juste une vérification rapide pour explorer les données), vous pouvez utiliser l'agrégation avec l'utilisation du disque:
all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})
(Je ne sais pas comment faire cela en pymongo, cependant).
Syntaxe de l'API JavaScript pour l'index:
db_handle.ensureIndex({executedDate: 1})
Dans mon cas, il était nécessaire de fixer les index nessary dans le code et de les recréer:
rake db:mongoid:create_indexes Rails_ENV=production
Comme le dépassement de mémoire ne se produit pas quand il y a un index de champ nécessaire.
PS Avant cela, je devais désactiver les erreurs lors de la création d'index longs:
# mongo
MongoDB Shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )
Peut aussi être nécessaire reIndex
:
# mongo
MongoDB Shell version: 2.6.12
connecting to: test
> use your_db
switched to db your_db
> db.getCollectionNames().forEach( function(collection){ db[collection].reIndex() } )