L'utilizzo dei dati bufferizzati nella fase di ordinamento di overflow supera il limite interno


85

Utilizzando il codice:

all_reviews = db_handle.find().sort('reviewDate', pymongo.ASCENDING)
print all_reviews.count()

print all_reviews[0]
print all_reviews[2000000]

Il conteggio viene stampato 2043484e viene stampato all_reviews[0].

Tuttavia, durante la stampa all_reviews[2000000], ottengo l'errore:

pymongo.errors.OperationFailure: errore del database: errore del runner: l'utilizzo di dati bufferizzati nella fase di ordinamento di overflow di 33554495 byte supera il limite interno di 33554432 byte

Come lo gestisco?

Risposte:


119

Stai raggiungendo il limite di 32 MB su un ordinamento in memoria:

https://docs.mongodb.com/manual/reference/limits/#Sort-Operations

Aggiungi un indice al campo di ordinamento. Ciò consente a MongoDB di trasmettere i documenti in ordine ordinato, piuttosto che tentare di caricarli tutti in memoria sul server e ordinarli in memoria prima di inviarli al client.


7
Meglio dichiarare un indice in modo da non dover ordinare nella RAM: più veloce e più affidabile, utilizzo limitato della RAM piuttosto che potenzialmente illimitato. Se insisti, trasforma la tua "ricerca" in un'aggregazione (che può utilizzare 100 MB di RAM per l'ordinamento) e imposta allowDiskUse: true per dire al framework di aggregazione di riversarsi sul disco se supera i 100 MB di RAM. Aspettatevi una grave penalizzazione delle prestazioni rispetto alla semplice dichiarazione di un indice appropriato. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
A. Jesse Jiryu Davis

32
In realtà, può essere cambiato. È necessario eseguire questo comando: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Fonte: askubuntu.com/questions/501937/…
kumarharsh

6
Buono a notare per gli utenti di mangusta che l'impostazione di index: true sull'elica nello schema risolverà questo problema ... mangusta esaminerà tutti i tuoi schemi e si assicurerà che i campi siano effettivamente indici prima di avviare l'app ... cioè a meno che disattivi questo comportamento con mySchema.set ('autoIndex', false);
Benjamin Conant

2
Ho creato un indice sul campo di ordinamento ma ancora mi dà questo errore "L'operazione di ordinamento ha utilizzato più del massimo 33554432 byte di RAM" potrebbe essere dovuto al fatto che sto applicando l'operazione di corrispondenza prima dell'ordinamento e secondo il documento mongo se usi la corrispondenza prima dell'ordinamento operazione trascurerà l'indice ed eseguirà l'ordinamento in memoria su tutti i record corrispondenti.
Amol Suryawanshi

11
Se questa è la risposta accettata, dovrebbe includere informazioni su come aggiungere un indice.
Philipp Ludwig

46

Come detto kumar_harshnella sezione commenti, vorrei aggiungere un altro punto.

È possibile visualizzare l'utilizzo del buffer corrente utilizzando il comando seguente sul admindatabase:

> use admin
switched to db admin
> db.runCommand( { getParameter : 1, "internalQueryExecMaxBlockingSortBytes" : 1 } )
{ "internalQueryExecMaxBlockingSortBytes" : 33554432, "ok" : 1 }

Ha un valore predefinito di 32 MB (33554432 byte) . In questo caso stai esaurendo i dati del buffer in modo da poter aumentare il limite del buffer con il tuo valore ottimale definito, ad esempio 50 MB come di seguito:

>  db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes:50151432})
{ "was" : 33554432, "ok" : 1 }

Possiamo anche impostare questo limite in modo permanente tramite il parametro seguente nel file di configurazione di mongodb:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

Spero che sia di aiuto !!!

Note: Questo comando supporta solo dopo la versione 3.0 +


Qual è il modo per impostare questo limite in modo permanente nel file di configurazione? Ho una macchina di memoria da 1 TB dedicata al mongo e vorrei aumentarla in modo permanente.
Samantha Atkins

@SamanthaAtkins Ho aggiornato la risposta per impostarlo in modo permanente nel file di configurazione.
JERRY

@ JERRY dove impostare in modo permanente nei binari. Rails 5 / mongoid.yml?
Prateep Kul

L'ho trovato. corri al mio terminale con: mongod e segui il manuale zocada.com/setting-mongodb-users-beginners-guide
Prateep Kul

24

risolto con indicizzazione

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])

assicurati di non utilizzare un indice sparse, vengono ignorati se ordini su ogni documento
Charly Koza

15

Se vuoi evitare di creare un indice (ad esempio, vuoi solo un controllo rapido e sporco per esplorare i dati), puoi usare l'aggregazione con l'utilizzo del disco:

all_reviews = db_handle.aggregate([{$sort: {'reviewDate': 1}}], {allowDiskUse: true})

(Non sono sicuro di come farlo in pymongo, però).


In pymongo sarebbe db_handle.aggregate(pipe, allowDiskUse=True). Vedi questa domanda per maggiori informazioni!
Genarito

3

Sintassi dell'API JavaScript per l'indice:

db_handle.ensureIndex({executedDate: 1})

2

Nel mio caso, era necessario correggere gli indici necessari nel codice e ricrearli:

rake db:mongoid:create_indexes RAILS_ENV=production

Poiché l'overflow della memoria non si verifica quando è necessario un indice di campo.

PS Prima di questo ho dovuto disabilitare gli errori durante la creazione di indici lunghi:

# mongo
MongoDB shell version: 2.6.12
connecting to: test
> db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

Potrebbe anche essere necessario 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() } )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.