Overview
MongoDB proporciona a los clientes la capacidad de realizar operaciones de escritura en bloque. Las operaciones de escritura masiva afectan a una única colección. MongoDB permite a las aplicaciones determinar el nivel aceptable de reconocimiento requerido para las operaciones de escritura en bloque.
La db.collection.bulkWrite() El método proporciona la capacidad de realizar operaciones de inserción, actualización y eliminación masivas.
MongoDB también admite la inserción masiva a través del método db.collection.insertMany().
Operaciones ordenadas frente a desordenadas
Las operaciones de escritura en masa pueden ser ordenadas o desordenadas.
Con una lista ordenada de operaciones, MongoDB ejecuta las operaciones de forma serial. Si se produce un error durante el procesamiento de una de las operaciones de guardar, MongoDB devolverá la operación sin procesar el resto de las operaciones de guardar de la lista. Ver Bulk guardar Ordenada
Con una lista desordenada de operaciones, MongoDB puede ejecutar las operaciones en paralelo, pero este comportamiento no está garantizado. Si se produce un error durante el procesamiento de una de las operaciones de guardar, MongoDB seguirá procesando las operaciones de guardar restantes en la lista. Consulta el Ejemplo de escritura masiva desordenada.
La ejecución de una lista ordenada de operaciones en una colección fragmentada generalmente será más lenta que la ejecución de una lista desordenada, ya que con una lista ordenada, cada operación debe esperar a que la operación anterior termine.
Por defecto, bulkWrite() realiza ordered operaciones. Para especificar unordered operaciones de guardar, establezca ordered : false en el documento de opciones.
Consulta Ejecución de operaciones
Métodos bulkWrite()
bulkWrite() admite las siguientes operaciones de escritura:
Cada operación de escritura se pasa a bulkWrite() como un documento en un arreglo.
Ejemplo
El ejemplo en esta sección utiliza la colección pizzas:
db.pizzas.insertMany( [ { _id: 0, type: "pepperoni", size: "small", price: 4 }, { _id: 1, type: "cheese", size: "medium", price: 7 }, { _id: 2, type: "vegan", size: "large", price: 8 } ] )
El siguiente ejemplo de bulkWrite() ejecuta estas operaciones en la colección pizzas:
Agrega dos documentos con
insertOne.Actualiza un documento con
updateOne.Elimina un documento con
deleteOne.Reemplaza un documento con
replaceOne.
try { db.pizzas.bulkWrite( [ { insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } }, { insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } }, { updateOne: { filter: { type: "cheese" }, update: { $set: { price: 8 } } } }, { deleteOne: { filter: { type: "pepperoni"} } }, { replaceOne: { filter: { type: "vegan" }, replacement: { type: "tofu", size: "small", price: 4 } } } ] ) } catch( error ) { print( error ) }
Ejemplo de salida, que incluye un resumen de las operaciones completadas:
{ acknowledged: true, insertedCount: 2, insertedIds: { '0': 3, '1': 4 }, matchedCount: 2, modifiedCount: 2, deletedCount: 1, upsertedCount: 0, upsertedIds: {} }
Para más ejemplos, consulta Ejemplos de bulkWrite().
Estrategias para inserciones masivas en una colección fragmentada
Las grandes operaciones de inserción masiva, incluidas las inserciones iniciales de datos o la importación rutinaria de datos, pueden afectar el rendimiento de un clúster fragmentado. Para inserciones masivas, considera las siguientes estrategias:
Pre-dividir la colección
Si su colección particionada está vacía y no está utilizando el particionado con hash para la primera clave de su clave de particionado, entonces su colección tiene solo un fragmento inicial, que reside en una sola partición. Luego, MongoDB debe tomarse un tiempo para recibir datos y distribuir fragmentos a los fragmentos disponibles. Para evitar este costo de rendimiento, divida previamente la colección creando rangos en un clúster.
Escrituras desordenados en mongos
Para mejorar el rendimiento de escritura en clústeres fragmentados, utiliza bulkWrite() con el parámetro opcional ordered configurado en false. mongos puede intentar enviar los datos a varias particiones simultáneamente. Para colecciones vacías, primero divide previamente la colección como se describe en Dividir fragmentos en un clúster particionado.
Evita la limitación monotónica
Si la clave de fragmentación aumenta de manera monotónica durante una inserción, entonces todos los datos insertados van al último fragmento en la colección, que siempre terminará en un solo fragmento. Por lo tanto, la capacidad de inserción del clúster nunca superará la capacidad de inserción de ese único fragmento.
Si el volumen de la inserción es mayor que lo que puede procesar un solo fragmento, y si no se puede evitar que una clave de fragmentación aumente de forma monotónica, se deben considerar las siguientes modificaciones en la aplicación:
Invierta los bits binarios de la clave de fragmentación. Esto preserva la información y evita correlacionar el orden de inserción con una secuencia creciente de valores.
Intercambia las primeras y últimas palabras de 16 bits para "barajar" las inserciones.
Ejemplo
El siguiente ejemplo, en C++, intercambia la palabra de 16 bits inicial y final de los tipos BSON ObjectIds generados para que no aumenten de forma monotónica.
using namespace mongo; OID make_an_id() { OID x = OID::gen(); const unsigned char *p = x.getData(); swap( (unsigned short&) p[0], (unsigned short&) p[10] ); return x; } void foo() { // create an object BSONObj o = BSON( "_id" << make_an_id() << "x" << 3 << "name" << "jane" ); // now we may insert o into a sharded collection }
Tip
Claves de fragmentación para obtener información sobre cómo elegir una clave de fragmentación. También consulta Componentes internos de claves de fragmentación (en particular, Elegir una clave de fragmentación).