2011-06-14 19 views
16

He leído que la incrustación es mejor desde el punto de vista del rendimiento: "Si el rendimiento es un problema, incrústelo". (http://www.mongodb.org/display/DOCS/Schema+Design) y la mayoría de las guías siempre dicen que debe contener incrustado.MongoDB incrustado vs. referencia desde la perspectiva de rendimiento

Sin embargo, no estoy seguro de que este sea el caso. Supongamos que tenemos dos objetos: Blog y Post. Blog contiene publicaciones.

Haciendo ahora todos los mensajes incrustados en el blog tendrá las siguientes cuestiones:

  1. Paging. Como no es posible filtrar objetos incrustados, siempre recibiremos todas las publicaciones y será necesario filtrarlas en la aplicación.
  2. Filtrado. Al igual que antes, al buscar palabras dentro de las publicaciones, no será posible filtrar la colección incrustada de MongoDB.
  3. Insertar. Supongo que insertar en la colección es más rápido que insertarlo en un objeto incrustado. ¿Es esto correcto? esto está escrito en cualquier lugar?
  4. Actualización. Igual que antes, el campo de actualización en línea dentro del documento más pequeño (Publicación) puede ser más rápido que la actualización en línea de la publicación dentro del documento grande de Blog. ¿Es esto correcto?

Tomando todo lo anterior, me gustaría tener publicaciones en una colección separada que hace referencia al blog. ¿Es esta la conclusión correcta?

(Nota: Por favor, no el factor límite de tamaño del documento en la respuesta, vamos a asumir cada blog tendrá como máximo 1000 mensajes)

Respuesta

12

1.Paging posible con $slice operador:

db.blogs.find({}, {posts:{$slice: [10, 10]}}) // skip 10, limit 10 

2.Filtering también posible:

db.blogs.find({"posts.title":"Mongodb!"}, {posts:{$slice: 1}}) //take one post 

3,4. En general, supongo que estás hablando de una pequeña diferencia de rendimiento. No es ciencia de cohetes, solo bloguea con un máximo de 1000 publicaciones.

Usted dijo:

Is this the correct conclusion? 

Sin, si se preocupan por el rendimiento (en general, si el sistema será pequeño se puede ir con el documento aparte).

que he hecho pequeña prueba de rendimiento con respecto a 3,4, es aquí los resultados:

----------------------------------------------------------------- 
| Count/Time | Inserting posts | Adding to nested collection | 
-------------|--------------------------------------------------    
| 1  | 1 ms    | 28 ms      | 
| 1000  | 81 ms   | 590 ms      | 
| 10000 | 759 ms   | 2723 ms     | 
--------------------------------------------------------------- 
+0

Gracias por la respuesta detallada. – mbdev

+0

@mbdev: de nada. –

+0

¿Estás seguro de que el # 2 devuelve el blog con una publicación que coincide con el título? Creo que devuelve el blog que contiene una publicación con "Mongodb!" título. Entonces slice solo filtrará la primera publicación. Entonces obtendrá una publicación incorrecta – mbdev

1
  1. Puede paginación con '$ rebanada' el elemento incrustado
  2. Puede buscar con "campo1.field2":/aRegex/ con aRegex es la palabra que busca. Pero cuida el rendimiento.

Acerca de 3. y 4. No tengo datos de prueba.

BTW 2 colecciones pueden ser más fáciles de codificar/usar/administrar. Y sólo tiene que registrarse en cada documento blogid 'blog' y añadir "blogid": "1234ABCD" en toda su consulta

2

En cuanto a 3 & 4, si se va a insertar en un documento anidada, que es básicamente una actualización.

Esto puede ser terriblemente malo para su rendimiento debido a que los insertos generalmente se anexan al final de los datos que funciona bien y rápido. Las actualizaciones, por otro lado, pueden ser mucho más complicadas.

Si su actualización no cambia el tamaño de un documento (lo que significa que tenía un par clave \ valor y simplemente cambió el valor a un nuevo valor que ocupa la misma cantidad de espacio), entonces estará bien pero cuando usted comienza a modificar documentos y agregar nuevos datos, surge un problema.

El problema es que mientras MongoDB asigna más espacio del necesario para cada documento, puede que no sea suficiente. Si inserta un documento que es 1k grande, MongoDB puede asignar 1,5k para el documento para garantizar que los cambios menores en el documento tengan espacio suficiente para crecer. Si usa más que el espacio asignado, MongoDB tiene que buscar el documento completo y volver a escribirlo en el extremo posterior de los datos.

Obviamente, hay una implicancia de rendimiento en la recuperación y reescritura de los datos que se amplificará por la frecuencia de dicha operación. Para empeorar las cosas, cuando esto sucede, terminas dejando agujeros o espacios sin usar en tus archivos de datos.

Esto finalmente se copia en la memoria lo que significa que puede terminar usando 2GB de RAM para almacenar su conjunto de datos, mientras que en realidad los datos solo toman 1.5GB porque hay un valor de .5GB de bolsillos. Esta fragmentación se puede evitar haciendo inserciones en lugar de actualizaciones. También se puede arreglar haciendo una reparación de la base de datos.

En la próxima versión de MongoDB habrá una función de compactación en línea.

+0

¿Crees que los números serán peores que los de Andrew? – mbdev

+0

Imposible decir que dependo 100% de la estructura de datos y el tamaño de sus documentos y documentos incrustados. Una vez que intente insertar un documento más grande que el espacio libre asignado, verá disminución del rendimiento en sus escrituras. Creo que será difícil probarlo con una pequeña prueba con un conjunto de datos relativamente pequeño. –

Cuestiones relacionadas