javascript - one - node js mongodb example
MongoDB: ¿cuál es la forma más rápida de actualizar todos los registros en una colección? (4)
Tengo una colección con 9 millones de registros. Actualmente estoy usando la siguiente secuencia de comandos para actualizar toda la colección:
simple_update.js
db.mydata.find().forEach(function(data) {
db.mydata.update({_id:data._id},{$set:{pid:(2571 - data.Y + (data.X * 2572))}});
});
Esto se ejecuta desde la línea de comando de la siguiente manera:
mongo my_test simple_update.js
Entonces, todo lo que hago es agregar un nuevo campo pid basado en un simple cálculo.
¿Hay una manera mas rápida? Esto toma una cantidad significativa de tiempo.
Estoy usando el método : db.collection.update
// db.collection.update( criteria, objNew, upsert, multi ) // --> for reference
db.collection.update( { "_id" : { $exists : true } }, objNew, upsert, true);
Hay dos cosas que puedes hacer.
- Envíe una actualización con el indicador ''multi'' establecido en verdadero.
- Almacene la función del lado del servidor e intente usar la ejecución del código del lado del servidor .
Ese enlace también contiene el siguiente consejo:
Esta es una buena técnica para realizar trabajo administrativo por lotes. Ejecute mongo en el servidor, conectándose a través de la interfaz localhost. La conexión es entonces muy rápida y de baja latencia. Esto es más amigable que db.eval () ya que db.eval () bloquea otras operaciones.
Este es probablemente el más rápido que obtendrá. Debe darse cuenta de que la emisión de actualizaciones de 9M en un solo servidor va a ser una operación pesada. Digamos que puedes obtener 3k actualizaciones / segundo, todavía estás hablando de correr durante casi una hora.
Y eso no es realmente un "problema mongo", va a ser una limitación de hardware.
No estoy seguro si será más rápido pero podría hacer una actualización múltiple. Simplemente diga update where _id > 0
(esto será cierto para cada objeto) y luego configure el indicador ''multi'' como verdadero y debería hacer lo mismo sin tener que iterar a través de toda la colección.
Mira esto: MongoDB - Ejecución del código del lado del servidor
No recomendaré el uso de {multi: true} para un conjunto de datos más grande, porque usa mucha CPU y menos configurable.
Como entusiasta mongodb, odio cuando la gente dice que el mongo es lento. Así que encontré una forma mejor de usar la inserción masiva.
La operación masiva es realmente útil para las tareas del programador. Supongamos que tiene que eliminar datos anteriores a 6 meses al día. Use la operación masiva. Es rápido y no ralentizará el servidor. La CPU, el uso de la memoria no se nota cuando se inserta, elimina o actualiza más de mil millones de documentos. {multi: true} ralentiza el servidor cuando se trata de millones de documentos.
Vea una muestra a continuación. Es un script de shell js, también puede ejecutarlo en el servidor como un programa de nodo (use el módulo npm shelljs o similar para lograr esto)
actualizar monogo a 3.2+
La vieja forma de actualizar ...
let counter = 0;
db.myCol.find({}).sort({$natural:1}).limit(1000000).forEach(function(document){
counter++;
document.test_value = "just testing" + counter
db.myCol.save(document)
});
Tardé 310-315 segundos cuando lo intenté. Eso es más de 5 minutos para actualizar un millón de documentos.
Mi colección incluye 100 millones de documentos +, por lo que la velocidad puede variar para los demás.
El mismo uso de inserción a granel es
let counter = 0;
// magic no.- depends on your hardware and document size. - my document size is around 1.5kb-2kb
// performance reduces when this limit is not in 1500-2500 range.
// try different range and find fastest bulk limit for your document size or take an average.
let limitNo = 2222;
let bulk = db.myCol.initializeUnorderedBulkOp();
let noOfDocsToProcess = 1000000;
db.myCol.find({}).sort({$natural:1}).limit(noOfDocsToProcess).forEach(function(document){
counter++;
noOfDocsToProcess --;
limitNo--;
bulk.find({_id:document._id}).update({$set:{test_value : "just testing .. " + counter}});
if(limitNo === 0 || noOfDocsToProcess === 0){
bulk.execute();
bulk = db.myCol.initializeUnorderedBulkOp();
limitNo = 2222;
}
});
El mejor momento fue 8972 millis. En promedio, tomó solo 10 segundos actualizar un millón de documentos. 30 veces más rápido que en el pasado.
Coloque el código en un archivo .js y ejecútelo como script mongo shell.
Si alguien encuentra una mejor manera, por favor actualice. Vamos a hacer mongo más rápido.