2011-11-04 12 views
13

Tenemos una colección de datos de registro, donde cada documento de la colección se identifica mediante una dirección MAC y un día calendario. Básicamente:En MongoDB, estrategia para maximizar el rendimiento de las escrituras en los documentos de registro diarios

{ 
    _id: <generated>, 
    mac: <string>, 
    day: <date>, 
    data: [ "value1", "value2" ] 
} 

Cada cinco minutos, añadimos una nueva entrada en el registro de la matriz de datos dentro del documento del día actual. El documento se transfiere a la medianoche UTC cuando creamos un nuevo documento para cada MAC.

Hemos notado que IO, medido por bytes escritos, aumenta durante todo el día y luego vuelve a bajar a la medianoche UTC. Esto no debería suceder porque la tasa de mensajes de registro es constante. Creemos que el comportamiento inesperado se debe a que Mongo mueve documentos, en lugar de actualizar sus matrices de registros. Por lo que vale, stats() muestra que el paddingFactor es 1.0299999997858227.

varias preguntas:

  1. ¿Hay una manera de confirmar si Mongo está actualizando en su lugar o en movimiento? Vemos algunos movimientos en el registro lento de consultas, pero esto parece una evidencia anecdótica. Sé que puedo db.setProfilingLevel(2), luego db.system.profile.find(), y finalmente busco "moved:true", pero no estoy seguro si está bien hacerlo en un sistema de producción ocupado.
  2. El tamaño de cada documento es muy predecible y regular. Suponiendo que mongo está haciendo muchos movimientos, ¿cuál es la mejor manera de descubrir por qué Mongo no puede preseleccionar con mayor precisión? ¿O para hacer que Mongo presfore con mayor precisión? Suponiendo que la descripción anterior del problema es correcta, ajustar el factor de relleno no parece ser suficiente.
  3. Debería ser bastante fácil para mí preseleccionar el documento y eliminar cualquier conjetura de Mongo. (Sé que los documentos padding factor dicen que no debería tener que hacer esto, pero necesito dejar este tema atrás). ¿Cuál es la mejor manera de preseleccionar un documento? Parece simple escribir un documento con un campo de matriz de bytes de basura, y luego eliminar inmediatamente ese campo del documento, pero ¿hay algún problema que deba tener en cuenta? Por ejemplo, puedo imaginar tener que esperar en el servidor para la operación de escritura (es decir, hacer una escritura segura) antes de eliminar el campo de basura.
  4. Estaba preocupado por la preasignación de todos los documentos de un día más o menos al mismo tiempo porque parece que esto saturaría el disco en ese momento. ¿Es esta una preocupación valida? ¿Debería tratar de distribuir los costos previos a la asignación el día anterior?
+0

Scott Hernandez respondió esta pregunta en el Grupo de Google, por lo que estoy publicando una lista en su respuesta: http://groups.google.com/group/mongodb-user/browse_thread/thread/8a24e7f3faf95f71# – jtoberon

+0

Última actualización: todavía estamos tratando de descubrir qué está pasando. – jtoberon

Respuesta

4

La siguiente combinación parece ser la causa rendimiento de escritura a caer por un precipicio:

  1. diario es sucesivamente.
  2. escrituras anexar entradas a una matriz que constituye la mayor parte de un documento más grande

Presumiblemente I/O se satura.Cambiar cualquiera de estos factores parece evitar que esto suceda:

  1. Desactivar el registro. Usa más réplicas en su lugar.
  2. Use documentos más pequeños. Tenga en cuenta que el tamaño del documento aquí se mide en bytes, no en la longitud de las matrices en los documentos.
  3. Diario en un sistema de archivos separado.

Además, aquí hay algunos otros trucos que mejoran el rendimiento de escritura. Con la excepción de sharding, encontramos que las mejoras eran incrementales, mientras que intentábamos resolver el problema de "esto no funciona para nada", pero las incluyo aquí en caso de que esté buscando mejoras incrementales . La gente de 10Gen did some testing and got similar results:

  1. Shard.
  2. Divida largas matrices en varias matrices, para que su estructura general se parezca más a un árbol anidado. Si usa la hora del día como la clave, el documento de registro diario se convierte en:
    {"0":[...], "1":[...],...,"23":[...]}.
  3. Intente la preasignación manual. (Esto no nos ayudó. El relleno de Mongo parece funcionar como se anuncia. Mi pregunta original estaba equivocada.)
  4. Pruebe diferentes valores de sincronización de sincronización. (Esto no nos ayudó.)
  5. Prueba sin escribir con seguridad. (Ya estábamos haciendo esto para los datos de registro, y no es posible en muchas situaciones. Además, esto parece un poco engañoso)

Notarás que he copiado algunas de las sugerencias de 10Gen aquí, solo por completitud. ¡Espero haberlo hecho tan exactamente! Si publican un ejemplo de libro de cocina, entonces publicaré un enlace aquí.

0

mongodb intentará preseleccionar documentos de forma adaptativa a medida que aprende cómo está actualizando documentos durante un período de tiempo. Puede encontrar más información en http://www.mongodb.org/display/DOCS/Padding+Factor

Si encuentra que mongodb aún está moviendo documentos después de un tiempo, puede probar manualmente rellenar el documento, para que no tenga que preocuparse por tener que mover documentos.

En su caso, parece que debería poder hacerlo, dado que el número de muestras en un día es constante (para su intervalo de 5 minutos). ¿Puede imprimir el resultado de db. {Yourcollectionname} .stats()?

En cuanto al punto n. ° 4: Puede distribuir los costos como mencionó, pero trataría de insertar los documentos cuando los necesite por primera vez para ver cómo funcionan y luego probar otras cosas.

tal vez pueda eludir este problema en particular explorando otros esquemas, pero no estoy seguro de todo lo que ha probado.¿Está almacenando pares de valores clave dentro de la matriz, siendo la marca de tiempo la clave? una modificación ejemplo sería mover a algo como: { ID: 1, métricas: { "00:05": { "métrica1": "valor1"}, "00:10": { " metric2 ":" value2 "} } }

+0

Estoy al tanto de las adaptaciones adaptativas, pero si funciona, entonces no creo que veamos el patrón IO que describí. Agregaré las estadísticas a la pregunta. Sí, me gustaría rellenar el documento manualmente; vea mi pregunta 3. ¿Puede proporcionar detalles sobre cómo hacerlo exactamente? Sí, estamos probando cosas, pero como dije, espero problemas, por lo que una respuesta de alguien con experiencia sería más útil. No creo que el esquema sea el núcleo de este problema, ya que cada escritura simplemente agrega el valor al final de un campo de matriz, pero he agregado un ejemplo a la pregunta por si acaso. – jtoberon

+0

¿Cuál es el factor de relleno que mongodb ha calculado para su colección? – Shekhar

+0

está en la pregunta: 1.0299999997858227 – jtoberon

0

Está haciendo una cantidad predecible/constante de impulsos en su matriz de datos. (24 * 60)/5 = 288 en un día. Recomiendo encarecidamente la asignación previa de 288 elementos de matriz (o 1000 para flexibilidad y expansión en caso de que decida hacerlo cada 3 minutos, por ejemplo) en el documento, y luego actualice el documento en consecuencia para cada adición de entrada de datos. Así es como proceder:

-Agregar 1 clave más a cada documento, esto mantendrá el número de clave para actualizar en la matriz asociativa data. p.ej. Inicialmente el documento se vería en primera inserción o actualización de matriz de datos de actualización

{ 
     _id: <generated>, 
     mac: <string>, 
     day: <date>, 
     data: { "1" : "myGarbageValue","2" : "myGarbageValue", 
       "3" : "myGarbageValue"....."1000": "myGarbageValue" } 
     n: 1 
} 

Para cada actualización, que tienes que hacer un upsert de data clave igual a n, y el incremento n después de 2 actualizaciones de datos:

{ 
      _id: <generated>, 
      mac: <string>, 
      day: <date>, 
      data: { "1" : "myFirstValue","2" : "mySecondValue", 
        "3" : "myGarbageValue"....."1000": "myGarbageValue" } 
      n: 3 
    } 

Pros:

  • Menos crecimiento de documento, sería b e mejor si su myGarbageValue, myFirstValue, mySecondValue son consistentes en tamaño y formato.
  • n siempre le dice el tamaño actual de su matriz data, y le permite ejecutar consultas de rango para encontrar data tamaño de matriz, que no era posible en su estructura anterior ya que el operador $ size solo puede devolver la coincidencia de tamaño exacto, sin rangos. http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24size
  • El rendimiento de actualización es mejor cuando el documento no se expande. Aquí se trata de una clave limpia basada en upsert, por ejemplo, en data.23, mientras que en la estructura anterior era $push que tiene un rendimiento de inserción lineal y se vuelve más lenta a medida que crece su matriz data.

Contras:

  • más espacio en disco es utilizado por sus datos, que no debería ser un problema, ya que actualice sus datos cada 24 horas.

Espero que estas sugerencias ayuden. Pruébalo y haznos saber a todos si te beneficia.

+0

¿Conoces la fuente oficial de la información del "empuje tiene un rendimiento de inserción lineal"? Conozco esta prueba http://blog.axant.it/archives/236, pero solo dice "probablemente". Intentaremos la sugerencia del conjunto asociativo, pero me sorprendería si esto funciona. Estamos muy por debajo del umbral de 5000 que se menciona. Además, no puedo pensar en una explicación de por qué un algoritmo de inserción lineal se traduciría en el comportamiento de IO físico que vemos, ya que no es posible que se mueva cada entrada. – jtoberon

+0

Hola, jtoberon, No documentado oficialmente, pero se observó durante algunas evaluaciones comparativas. Sin embargo, para un conjunto de 288 tamaños pequeños como el tuyo, eso no hará mucha diferencia. Y tiene razón, la diferencia IO no se realiza mediante la diferencia de algoritmo de inserción/actualización, sino que está hecha por el hecho de que debido a la preasignación de elementos en la matriz asociativa, el objeto del documento no crece. Por lo tanto, mongodb , menos IO. – DhruvPathak

+0

El cambio de matriz asociativa no ayudó. La carga de IO se suaviza, pero a un nivel que es peor que los picos de lo que vemos cuando usamos una matriz normal y '$ push'. – jtoberon

Cuestiones relacionadas