Diseño de esquema de MongoDB: ¿muchos documentos pequeños o menos documentos grandes?

88

Antecedentes
Estoy creando un prototipo de una conversión de nuestra base de datos RDBMS a MongoDB. Mientras desnormalizo, parece que tengo dos opciones, una que conduce a muchos (millones) de documentos más pequeños o otra que conduce a menos (cientos de miles) documentos grandes.

Si pudiera resumirlo en un simple análogo, sería la diferencia entre una colección con menos documentos del Cliente como este (en Java):

clase Cliente {
    nombre de cadena privada;
    dirección de dirección privada;
    // cada CreditCard tiene cientos de instancias de pago
    privado Establecer tarjetas de crédito <CreditCard>;
}

o una colección con muchos, muchos documentos de pago como este:

pago de clase {
    cliente cliente privado;
    CreditCard privada creditCard;
    fecha privada fecha de pago;
    payAmount flotante privado;
}

Pregunta
¿MongoDB está diseñado para preferir muchos, muchos documentos pequeños o menos documentos grandes? ¿La respuesta depende principalmente de las consultas que planeo ejecutar? (es decir, ¿cuántas tarjetas de crédito tiene el cliente X? vs ¿Cuál fue el monto promedio que pagaron todos los clientes el mes pasado?)

He mirado mucho a mi alrededor, pero no encontré ninguna de las mejores prácticas de esquema de MongoDB que me ayudarían a responder mi pregunta.

Andre
fuente

Respuestas:

82

Definitivamente necesitará optimizar las consultas que está haciendo.

Aquí está mi mejor suposición basada en su descripción.

Probablemente querrá conocer todas las tarjetas de crédito de cada cliente, así que mantenga una variedad de ellas dentro del objeto del cliente. Probablemente también desee tener una referencia de Cliente para cada Pago. Esto hará que el documento de pago sea relativamente pequeño.

El objeto de pago tendrá automáticamente su propio ID e índice. Probablemente también desee agregar un índice en la referencia del cliente.

Esto le permitirá buscar rápidamente Pagos por Cliente sin almacenar todo el objeto del cliente cada vez.

Si desea responder preguntas como "¿Cuál fue el monto promedio que pagaron todos los clientes el mes pasado?" , En cambio, querrá un mapa / reducción para cualquier conjunto de datos considerable. No obtiene esta respuesta "en tiempo real". Descubrirá que almacenar una "referencia" al Cliente probablemente sea lo suficientemente bueno para estas reducciones de mapas.

Entonces, para responder a su pregunta directamente: ¿MongoDB está diseñado para preferir muchos, muchos documentos pequeños o menos documentos grandes?

MongoDB está diseñado para encontrar entradas indexadas muy rápidamente. MongoDB es muy bueno para encontrar algunas agujas en un gran pajar. MongoDB no es muy bueno para encontrar la mayoría de las agujas en el pajar. Así que cree sus datos en torno a sus casos de uso más comunes y escriba mapas / reduzca trabajos para los casos de uso más raros.

Vicepresidente de Gates
fuente
30

Según la propia documentación de MongoDB, parece que está diseñado para muchos documentos pequeños.

De las mejores prácticas de rendimiento para MongoDB :

El tamaño máximo para documentos en MongoDB es 16 MB. En la práctica, la mayoría de los documentos tienen unos pocos kilobytes o menos. Considere los documentos más como filas en una tabla que como las propias tablas. En lugar de mantener listas de registros en un solo documento, convierta cada registro en un documento.

De 6 reglas generales para el diseño de esquemas de MongoDB: Parte 1 :

Modelado de uno a pocos

Un ejemplo de "uno a pocos" podrían ser las direcciones de una persona. Este es un buen caso de uso para la incrustación: colocaría las direcciones en una matriz dentro de su objeto Person.

Uno a muchos

Un ejemplo de "uno a varios" podría ser las piezas de un producto en un sistema de pedido de piezas de repuesto. Cada producto puede tener hasta varios cientos de piezas de repuesto, pero nunca más de un par de miles. Este es un buen caso de uso para hacer referencia: pondría los ObjectID de las partes en una matriz en el documento del producto.

Uno a Squillions

Un ejemplo de "uno a escuillones" podría ser un sistema de registro de eventos que recopila mensajes de registro para diferentes máquinas. Cualquier host dado podría generar suficientes mensajes para desbordar el tamaño del documento de 16 MB, incluso si todo lo que almacenó en la matriz fuera el ObjectID. Este es el caso de uso clásico de "referencias a los padres": tendría un documento para el host y luego almacenaría el ObjectID del host en los documentos para los mensajes de registro.

bmaupin
fuente
11

Los documentos que crecen sustancialmente con el tiempo pueden ser bombas de tiempo. Es probable que el ancho de banda de la red y el uso de RAM se conviertan en cuellos de botella medibles, lo que lo obligará a comenzar de nuevo.

Primero, consideremos dos cobros: Cliente y Pago. Así, el grano es bastante pequeño: un documento por pago.

A continuación, debe decidir cómo modelar la información de la cuenta, como las tarjetas de crédito. Consideremos si los documentos del cliente contienen matrices de información de cuenta o si necesita una nueva colección de cuenta.

Si los documentos de la cuenta están separados de los documentos del cliente, cargar todas las cuentas de un cliente en la memoria requiere buscar varios documentos. Eso podría traducirse en memoria adicional, E / S, ancho de banda y uso de CPU. ¿Significa eso inmediatamente que el cobro de la cuenta es una mala idea?

Su decisión afecta los documentos de pago. Si la información de la cuenta está incrustada en un documento del cliente, ¿cómo lo haría referencia? Los documentos de cuenta independientes tienen su propio atributo _id. Con la información de la cuenta incorporada, su aplicación generaría nuevos ID para las cuentas o usaría los atributos de la cuenta (por ejemplo, el número de cuenta) para la clave.

¿Podría un documento de pago contener realmente todos los pagos realizados en un plazo fijo (por ejemplo, un día?). Tal complejidad afectará a todo el código que lee y escribe documentos de pago. La optimización prematura puede ser mortal para los proyectos.

Al igual que los documentos de cuenta, los pagos se pueden consultar fácilmente siempre que un documento de pago contenga solo un pago. Un nuevo tipo de documento, crédito por ejemplo, podría hacer referencia a un pago. Pero, ¿crearía una colección de crédito o incrustaría información de crédito dentro de la información de pago? ¿Qué pasaría si más tarde necesitara hacer referencia a un crédito?

En resumen, he tenido éxito con muchos documentos pequeños y muchas colecciones. Implemento referencias con _id y solo con _id. Por lo tanto, no me preocupa que los documentos en constante crecimiento destruyan mi aplicación. El esquema es fácil de entender e indexar porque cada entidad tiene su propia colección. Las entidades importantes no se esconden dentro de otros documentos.

Me encantaría conocer sus hallazgos. ¡Buena suerte!

Terris
fuente