2011-06-14 3 views
16

J'ai lu que l'intégration est meilleure du point de vue des performances: "Si les performances sont un problème, intégrez". (http://www.mongodb.org/display/DOCS/Schema+Design) et la plupart des guides disent toujours que le contenu doit être incorporé.MongoDB intégré par rapport à la perspective de performance

Cependant, je ne suis pas sûr que ce soit le cas. Supposons que nous ayons deux objets: Blog et Post. Blog contient des messages.

maintenant faire tous les messages intégrés dans le blog auront les questions suivantes:

  1. Paging. Comme il n'est pas possible de filtrer les objets incorporés, nous recevons toujours tous les messages et nous devons les filtrer dans l'application.
  2. Filtrage. Comme précédemment, lors de la recherche de mots dans les publications, il ne sera pas possible de filtrer la collection intégrée de MongoDB.
  3. Insérez. Je suppose que l'insertion dans la collection est plus rapide que l'insertion dans un objet incorporé. Est-ce correct? ceci est écrit n'importe où?
  4. Mise à jour. Comme précédemment, le champ de mise à jour en ligne dans un document plus petit (Post) peut être plus rapide que la mise à jour en ligne du message dans le gros document de Blog. Est-ce correct?

En prenant tout ce qui précède, je voudrais aller pour avoir des messages dans une collection distincte Blog de référence. Est-ce la bonne conclusion?

(Note: S'il vous plaît ne limite la taille du document ne facteur dans la réponse, supposons que chaque blog aura au plus 1000 messages)

Répondre

12

1.Paging possible avec $slice opérateur:

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

2.Filtering aussi possible:

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

3,4. Généralement je suppose que vous parlez de petite différence de performance. Ce n'est pas sorcier, il suffit de bloguer avec au plus 1000 messages.

Vous avez dit:

Is this the correct conclusion? 

Pas, si vous vous souciez de la performance (en général si le système sera faible, vous pouvez aller avec le document séparé).

J'ai fait petit test de performance en ce qui concerne 3,4, voici les résultats:

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

Merci pour la réponse détaillée. – mbdev

+0

@mbdev: vous êtes les bienvenus. –

+0

Etes-vous sûr que # 2 renvoie le blog avec un article correspondant au titre? Je pense qu'il renvoie le blog contenant un message avec "Mongodb!" Titre. Ensuite, la tranche ne ferait que filtrer le premier message. Donc, vous obtiendrez post incorrect – mbdev

1
  1. Vous pouvez pagination avec « tranche de $ » sur l'élément embarqué
  2. Vous pouvez rechercher avec "field1.field2":/aRegex/ avec aRegex est le mot que vous recherchez. Mais prenez soin de la performance.

Environ 3. et 4. Je n'ai pas de données de preuve.

BTW 2 collections peuvent être plus faciles à coder/utiliser/gérer. Et vous pouvez simplement vous inscrire blogid dans chaque document 'blog' et ajouter "blogid": "1234ABCD" dans toute votre requête

2

Comme pour 3 & 4, si vous insérez dans un document imbriqué, il est essentiellement une mise à jour.

Cela peut être terriblement mauvais pour votre performance car les inserts sont généralement ajoutés à la fin des données, ce qui fonctionne très bien et rapidement. Les mises à jour, d'un autre côté, peuvent être beaucoup plus compliquées. Si votre mise à jour ne change pas la taille d'un document (ce qui signifie que vous avez une paire clé/valeur et que vous modifiez simplement la valeur à une nouvelle valeur occupant la même quantité d'espace), cela ne pose aucun problème. vous commencez à modifier les documents et à ajouter de nouvelles données, un problème se pose.

Le problème est que si MongoDB alloue plus d'espace que nécessaire pour chaque document, cela peut ne pas être suffisant. Si vous insérez un document de 1 Ko de large, MongoDB peut attribuer 1,5 Ko pour le document afin de garantir que les modifications mineures apportées au document disposent de suffisamment d'espace pour se développer. Si vous utilisez plus que l'espace alloué, MongoDB doit récupérer le document entier et le réécrire à la fin des données.

Il y a évidemment une implication de performance dans l'extraction et la réécriture des données qui seront amplifiées par la fréquence d'une telle opération. Pour aggraver les choses, quand cela arrive, vous finissez par laisser des trous ou des poches d'espace inutilisé dans vos fichiers de données. Cela finit par être copié en mémoire, ce qui signifie que vous pouvez utiliser 2 Go de RAM pour stocker votre ensemble de données, alors qu'en réalité, les données ne prennent que 1,5 Go, car il y a 0,5 Go de poches. Cette fragmentation peut être évitée en faisant des insertions par opposition aux mises à jour. Il peut également être réparé en faisant une réparation de base de données.

Dans la prochaine version de MongoDB, il y aura une fonction de compactage en ligne.

+0

Vous pensez que les chiffres seront plus mauvais que ceux d'Andrew? – mbdev

+0

Impossible à dire - je dépend à 100% de la structure de vos données et de la taille de vos documents et de vos documents incorporés. Une fois que vous essayez d'insérer un document plus grand que l'espace libre alloué, vous allez voir les performances diminuer sur vos écritures. Je pense que ce sera difficile à prouver avec un petit test avec un ensemble de données relativement petit. –

Questions connexes