2010-06-14 7 views
70

Antecedentes
estoy prototipos de una conversión de 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.MongoDB Schema Design: ¿muchos documentos pequeños o menos documentos grandes?

Si pudiera destilar a un simple analógica, sería la diferencia entre una colección con un menor número de documentos de clientes como esto (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 de esta manera:

 
class Payment { 
    private Customer customer; 
    private CreditCard creditCard; 
    private Date payDate; 
    private float payAmount; 
} 

pregunta
Está diseñado para MongoDB prefieren muchos, muchos documentos pequeños o un menor número de documentos de gran tamaño? ¿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 mirado mucho pero no tropecé con ninguna de las mejores prácticas del esquema de MongoDB que ayudaría yo respondo mi pregunta

Respuesta

71

Definitivamente tendrá que optimizar las consultas que está haciendo.

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

Es probable que desee conocer todas las tarjetas de crédito para cada cliente, por lo que debe mantener una variedad 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 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 todo el tiempo.

Si desea responder preguntas como "¿Cuál fue la cantidad promedio que pagaron todos los clientes el mes pasado?, en su lugar 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.

Para responder a su pregunta directamente: ¿MongoDB está diseñado para preferir muchos, muchos documentos pequeños o menos documentos de gran tamaño?

MongoDB está diseñado para encontrar entradas indexadas muy rápidamente. MongoDB es muy bueno para encontrar una pocas agujas en un gran pajar. MongoDB es no muy bueno en encontrar más 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.

5

Los documentos que crecen sustancialmente con el tiempo pueden convertirse en bombas de relojería. 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 cuenta son independientes de los documentos del cliente, cargar todas las cuentas para 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 a 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 en realidad contener 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?

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 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 conocer sus conclusiones. ¡Buena suerte!

9

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

De Performance Best Practices for MongoDB:

El tamaño máximo de los 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 haga que cada registro sea un documento .

De 6 Rules of Thumb for MongoDB Schema Design: Part 1:

Modelado de uno a pocos

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

-uno a varios

Un ejemplo de “uno a muchos” podrían ser partes de un producto en un piezas de repuesto sistema de pedidos. Cada producto puede tener hasta varias piezas de repuesto , pero nunca más de un par de miles o . Este es un buen caso de uso para hacer referencia: colocaría los ObjectID de las partes en una matriz en el documento del producto.

uno a squillions

Un ejemplo de “uno-a-squillions” podría ser un sistema de registro de eventos que recopila mensajes para diferentes máquinas de registro. Cualquier host dado podría generar suficientes mensajes para desbordar el tamaño de documento de 16 MB, , incluso si todo lo que almacenaba en la matriz era el ObjectID. Este es el caso de uso clásico para "referencia de padres" - usted tendría un documento para el host, y luego almacena el ObjectID del host en los documentos para los mensajes de registro.

Cuestiones relacionadas