c# - net - Cómo mejorar el rendimiento del inserto MongoDB
mongodb driver net core (4)
El resultado:
Si está operando en un conjunto de datos que es tolerante a fallas, o si está realizando un proceso de una sola vez que puede verificar, puede ser útil cambiar WriteAcknowledge a Unewnowledged.
Además, las operaciones masivas son IsOrdered de forma predeterminada, que no tenía conocimiento de desactivación. Establecer esto en Falso en realidad hace que la operación se realice de forma masiva, de lo contrario, funciona como un hilo de actualizaciones.
MongoDB 3.0 / WiredTiger / C # Driver
Tengo una colección con 147,000,000 de documentos, de los cuales estoy realizando actualizaciones cada segundo (con suerte) de aprox. 3000 documentos.
Aquí hay un ejemplo de actualización:
"query" : {
"_id" : BinData(0,"UKnZwG54kOpT4q9CVWbf4zvdU223lrE5w/uIzXZcObQiAAAA")
},
"updateobj" : {
"$set" : {
"b" : BinData(0,"D8u1Sk/fDES4IkipZzme7j2qJ4oWjlT3hvLiAilcIhU="),
"s" : true
}
}
Esta es una actualización típica de la cual mis requisitos deben insertarse a una velocidad de 3000 por segundo.
Desafortunadamente, estos están demorando el doble, por ejemplo, la última actualización fue para 1723 documentos y tomó 1061 ms.
La colección solo tiene un índice en el _id, ningún otro índice, y el tamaño promedio de documento para la colección es de 244 bytes, sin límite.
El servidor tiene 64GB de memoria, 12 hilos. El rendimiento del inserto es excelente con tamaños de colección más bajos, por ejemplo, alrededor de 50 millones, pero después de unos 80 millones realmente comienza a disminuir.
¿Podría ser porque todo el conjunto no queda en la memoria? La base de datos está respaldada por los SSD RAID0, por lo que el rendimiento de IO no debería convertirse en un cuello de botella y si lo fuera, debería haberlo mostrado al principio.
Apreciaría cierta orientación, ya que estoy seguro de que MongoDB puede cumplir mis requisitos más bien escasos en comparación con algunas aplicaciones en las que se utiliza. No hay una tasa de lectura sustancial en la base de datos, por lo que Sharding no mejoraría las cosas, aunque quizás esté equivocado.
De cualquier manera, la tasa de inserción actual no es lo suficientemente buena.
Actualización: Aquí está la explicación () de solo la consulta ...
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "Collection",
"indexFilterSet" : false,
"parsedQuery" : {
"_id" : {
"$eq" : { "$binary" : "SxHHwTMEaOmSc9dD4ng/7ILty0Zu0qX38V81osVqWkAAAAAA", "$type" : "00" }
}
},
"winningPlan" : {
"stage" : "IDHACK"
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 1,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "IDHACK",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needFetch" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keysExamined" : 1,
"docsExamined" : 1
},
"allPlansExecution" : []
},
La consulta en sí misma es muy rápida, y la operación de actualización toma unos 25 milisegundos, se están enviando a Mongo mediante el uso de BulkWriter: await m_Collection.BulkWriteAsync(updates);
"No hay una tasa de lectura sustancial en la base de datos, por lo que Sharding no mejoraría las cosas, aunque quizás esté equivocado".
Una actualización implica una lectura. También es posible encontrar ese abandono _id, por lo que tal vez la fragmentación podría ser útil si no es útil
La respuesta marcada aquí es buena. Quiero agregar un código adicional para ayudar a otros que usan InsertMany
lugar de BulkWriteAsync
a beneficiarse de IsOrdered = false
más rápido
m_Collection.InsertMany(listOfDocument, new InsertManyOptions() { IsOrdered = false });
Nos cambiamos a Cassandra porque Mongo no escala bien. Si dice que después de 80M vio una degradación del rendimiento, fácilmente se relaciona con la memoria. Soy más experto en bases de datos SQL pero no diría que 25 ms para una actualización de campo no clave es impresionante. Sospecho que una actualización similar funcionaría mejor en Oracle, MySql, ...
Puede intentar modificar los niveles de preocupación de escritura . Obviamente, existe un riesgo en esto, ya que no podría detectar ningún error de escritura, pero al menos debería poder capturar errores de red. Como MongoDB agrupa las operaciones de inserción masiva en grupos de 1000 , esto debería acelerar el proceso.
W por defecto es 1:
Cuando lo cambias a 0:
Si no le preocupa el orden de los elementos, puede ganar algo de velocidad llamando a la operación masiva no ordenada
await m_Collection.BulkWriteAsync(updates, new BulkWriteOptions() { IsOrdered = false });
Con una lista de operaciones desordenadas, MongoDB puede ejecutar en paralelo las operaciones de escritura en la lista y en cualquier orden. Link