database design - registro - Diseño de esquema MongoDB: ¿muchos documentos pequeños o menos documentos grandes?
mongodb modificar documento (3)
Fondo
Estoy creando prototipos de una conversión desde nuestra base de datos RDBMS a MongoDB. Mientras se desnormaliza, parece que tengo dos opciones, una que conduce a muchos (millones) de documentos más pequeños o una que conduce a menos (cientos de miles) de documentos de gran tamaño.
Si pudiera destilarlo en un análogo simple, sería la diferencia entre una colección con menos documentos del cliente como este (en Java):
class Customer { private String name; private Address address; // each CreditCard has hundreds of Payment instances private Set<CreditCard> creditCards; }
o una colección con muchos, muchos documentos de pago como este:
class Payment { private Customer customer; private CreditCard creditCard; private Date payDate; private float payAmount; }
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 la cantidad promedio que pagaron todos los clientes el mes pasado?)
He buscado mucho pero no tropecé con ninguna de las mejores prácticas de esquema de MongoDB que me ayudaría a responder mi pregunta.
Definitivamente tendrá que optimizar las consultas que está haciendo.
Aquí está mi mejor estimación basada en su descripción.
Probablemente desee conocer todas las tarjetas de crédito para cada cliente, así que mantenga una serie de ellas dentro del objeto del cliente. También es probable que desee tener una referencia de cliente para cada pago. Esto mantendrá el documento de pago relativamente pequeño.
El objeto Pago tendrá automáticamente su propia 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 en todo momento.
Si desea responder preguntas como "¿Cuál fue la cantidad promedio que pagaron todos los clientes el mes pasado?" , En cambio, va a querer un mapa / reducir para cualquier conjunto de datos de gran tamaño. No obtendrás esta respuesta "en tiempo real". Descubrirá que almacenar una "referencia" al Cliente probablemente sea lo suficientemente bueno para estos mapas-reduce.
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. Por lo tanto, construya sus datos alrededor de los casos de uso más comunes y escriba trabajos de mapa / reducción para los casos de uso más raros.
Los documentos que crecen sustancialmente con el tiempo pueden ser bombas de tiempo. El ancho de banda de la red y el uso de RAM probablemente se conviertan en cuellos de botella mensurables, lo que le obligará a comenzar de nuevo.
Primero, consideremos dos colecciones: Cliente y Pago. Por lo tanto, 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 son independientes de los documentos del cliente, cargar todas las cuentas de un cliente en la memoria requiere recuperar varios documentos. Eso podría traducirse en memoria extra, E / S, ancho de banda y uso de la CPU. ¿Eso significa inmediatamente que la recopilación de la cuenta es una mala idea?
Su decisión afecta los documentos de pago. Si la información de la cuenta está integrada en un documento del cliente, ¿cómo la haría referencia? Los documentos de cuenta separados tienen su propio atributo _id. Con la información de cuenta integrada, su aplicación generaría nuevos ID para las cuentas o usaría los atributos de la cuenta (por ejemplo, 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, día?). Tal complejidad afectará a todos los códigos que leen y escriben documentos de pago. La optimización prematura puede ser mortal para los proyectos.
Al igual que los documentos de cuenta, los pagos se referencian fácilmente siempre que un documento de pago contenga solo un pago. Un nuevo tipo de documento, por ejemplo crédito, podría hacer referencia a un pago. ¿Pero crearías una colección de crédito o insertarías 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?
Para resumir, he tenido éxito con muchos documentos pequeños y muchas colecciones. Implemento referencias con _id y solo con _id. Por lo tanto, no me preocupo por los documentos en constante crecimiento que destruyen 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 escuchar tus hallazgos. ¡Buena suerte!
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 de 16 MB. En la práctica, la mayoría de los documentos son de algunos kilobytes o menos. Considere los documentos más como filas en una tabla que las tablas mismas. En lugar de mantener listas de registros en un solo documento, en su lugar convierta cada registro en un documento.
De 6 Reglas de oro para el diseño de esquemas MongoDB: Parte 1 :
Modelado de uno a pocos
Un ejemplo de "uno a pocos" podría ser las direcciones para una persona. Este es un buen caso de uso para la incrustación: pondría las direcciones en una matriz dentro de su objeto Person.
Uno a muchos
Un ejemplo de "uno a muchos" podría ser partes 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 más o menos. 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 "one-to-squillions" 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 fue el ObjectID. Este es el caso de uso clásico para "referencias de padres": tendría un documento para el host y luego almacenaría el ObjectID del host en los documentos para los mensajes de registro.