El uso de datos almacenados en búfer de la etapa de clasificación de desbordamiento supera el límite interno

85

Usando el código:

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

print all_reviews[0]
print all_reviews[2000000]

El recuento se imprime 2043484y se imprime all_reviews[0].

Sin embargo, al imprimir all_reviews[2000000], aparece el error:

pymongo.errors.OperationFailure: error de base de datos: error de ejecución: el uso de datos almacenados en búfer de la etapa de clasificación de desbordamiento de 33554495 bytes excede el límite interno de 33554432 bytes

¿Cómo manejo esto?

sheetal_158
fuente

Respuestas:

118

Está llegando al límite de 32 MB en una clasificación en memoria:

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

Agregue un índice al campo de clasificación. Eso permite que MongoDB transmita documentos en orden ordenado, en lugar de intentar cargarlos todos en la memoria del servidor y ordenarlos en la memoria antes de enviarlos al cliente.

A. Jesse Jiryu Davis
fuente
7
Es mejor declarar un índice para no tener que ordenar en RAM: más rápido y más confiable, uso limitado de RAM en lugar de potencialmente ilimitado. Si insiste, convierta su "búsqueda" en una agregación (que puede usar 100 MB de RAM para ordenar) y configure allowDiskUse: true para decirle al marco de agregación que se derrame en el disco si excede los 100 MB de RAM. Espere una penalización de rendimiento severa en comparación con simplemente declarar un índice apropiado. docs.mongodb.org/manual/reference/operator/aggregation/sort/…
A. Jesse Jiryu Davis
31
De hecho, se puede cambiar. Es necesario ejecutar este comando: db.adminCommand({setParameter: 1, internalQueryExecMaxBlockingSortBytes: <limit in bytes>}). Fuente: askubuntu.com/questions/501937/…
kumarharsh
6
Es bueno tener en cuenta para los usuarios de mangosta que la configuración de index: true en el accesorio en su esquema solucionará este problema ... mongoose revisará todos sus esquemas y se asegurará de que los campos sean de hecho índices antes de iniciar la aplicación ... es decir, a menos que apaga este comportamiento con mySchema.set ('autoIndex', false);
Benjamin Conant
2
He creado un índice en el campo de clasificación, pero todavía me da este error de "La operación de clasificación utilizó más que el máximo de 33554432 bytes de RAM" puede deberse a que estoy aplicando la operación de coincidencia antes de la clasificación y de acuerdo con mongo doc si usa la coincidencia antes de la clasificación operación descuidará el índice y se realizará en la clasificación de memoria sobre todos los registros coincidentes.
Amol Suryawanshi
11
Si esta es la respuesta aceptada, debe incluir información sobre cómo agregar un índice.
Philipp Ludwig
45

Como se dijo kumar_harshen la sección de comentarios, me gustaría agregar otro punto.

Puede ver el uso actual del búfer usando el siguiente comando sobre la adminbase de datos:

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

Tiene un valor predeterminado de 32 MB (33554432 bytes) . En este caso, se está quedando sin datos del búfer, por lo que puede aumentar el límite del búfer con su propio valor óptimo definido, ejemplo 50 MB como se muestra a continuación:

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

También podemos establecer este límite de forma permanente mediante el siguiente parámetro en el archivo de configuración de mongodb:

setParameter=internalQueryExecMaxBlockingSortBytes=309715200

Espero que esto ayude !!!

Note: Este comando es compatible solo después de la versión 3.0 +

ALEMÁN
fuente
¿Cuál es la forma de establecer este límite de forma permanente en el archivo de configuración? Tengo una máquina de memoria de 1 TB dedicada a mongo y me gustaría ponerla en marcha de forma permanente.
Samantha Atkins
@SamanthaAtkins He actualizado la respuesta para configurar esto permanentemente en el archivo de configuración.
JERRY
@JERRY donde colocar permanentemente en rieles. Rails 5 / mongoid.yml?
Prateep Kul
Lo encontré. corre en mi terminal con: mongod y sigue el manual zocada.com/setting-mongodb-users-beginners-guide
Prateep Kul
24

resuelto con indexación

db_handle.ensure_index([("reviewDate", pymongo.ASCENDING)])
sheetal_158
fuente
asegúrese de no utilizar un índice escaso, se ignoran si ordena en cada documento
Charly Koza
15

Si desea evitar la creación de un índice (por ejemplo, solo desea una verificación rápida y sucia para explorar los datos), puede usar la agregación con el uso del disco:

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

(Sin embargo, no estoy seguro de cómo hacer esto en pymongo).

poroszd
fuente
En pymongo estaría db_handle.aggregate(pipe, allowDiskUse=True). Consulte esta pregunta para obtener más información.
Genarito
3

Sintaxis de la API de JavaScript para el índice:

db_handle.ensureIndex({executedDate: 1})
wytten
fuente
2

En mi caso, fue necesario arreglar los índices necesarios en el código y volver a crearlos:

rake db:mongoid:create_indexes RAILS_ENV=production

Como el desbordamiento de la memoria no ocurre cuando hay un índice de campo necesario.

PD Antes de esto, tuve que deshabilitar los errores al crear índices largos:

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

También puede ser necesario 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() } )
Shilovk
fuente