MongoDB嵌入式与性能角度的参考

时间:2011-06-14 14:34:45

标签: performance database-design mongodb

我从性能的角度看,嵌入效果更好: “如果表现是一个问题,请嵌入。” (http://www.mongodb.org/display/DOCS/Schema+Design)和大多数指南总是说应该嵌入包含。

但我不确定是这种情况。假设我们有两个对象:Blog和Post。博客包含帖子。

现在将所有帖子嵌入博客中都会出现以下问题:

  1. 寻呼即可。由于无法过滤嵌入的对象,我们将始终获取所有帖子,并需要在应用程序中对其进行过滤。
  2. 过滤即可。与之前相同,当在帖子中搜索单词时,将无法从MongoDB中过滤嵌入的集合。
  3. 插入即可。我假设插入到集合比插入嵌入对象更快。它是否正确?这写在任何地方?
  4. 更新即可。与之前相同,较小文档(Post)中的内联更新字段可能比内联更新Blog大文档中的帖子更快。这是对的吗?
  5. 考虑到以上所有内容,我会在一个引用Blog的单独集合中发帖。这是正确的结论吗?

    (注意:请不要在响应中考虑文档大小限制,假设每个博客最多有1000个帖子)

3 个答案:

答案 0 :(得分:12)

1.使用$slice运营商进行分页:

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

2.过滤也可能:

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

3,4。一般来说,我猜你说的是小的性能差异。这不是火箭科学,只是博客最多1000个帖子。

你说:

Is this the correct conclusion?

,如果您关心性能(一般情况下,如果系统很小,您可以使用单独的文档)。

我做了关于3,4的小型性能测试,结果如下:

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

答案 1 :(得分:3)

至于3& 4,如果要插入嵌套文档,它基本上是一个更新。

这对您的性能来说非常糟糕,因为插入通常会附加到数据的末尾,而且工作正常且速度很快。另一方面,更新可能会更加棘手。

如果您的更新没有更改文档的大小(意味着您有一个键\值对,只是将值更改为占用相同空间量的新值)那么您将会没事,但是当您开始修改文档并添加新数据,就会出现问题。

问题在于,虽然MongoDB分配的空间超出了每个文档所需的空间,但可能还不够。如果您插入1k大的文档,MongoDB可能会为文档分配1.5k,以确保对文档的微小更改有足够的空间来增长。如果使用的空间超过分配的空间,MongoDB必须获取整个文档并在数据的尾端重新写入。

在获取和重写数据方面显然存在性能影响,这将通过这种操作的频率放大。更糟糕的是,当发生这种情况时,最终会在数据文件中留下漏洞或未使用的空间。

这最终会被复制到内存中,这意味着您最终可能会使用2GB的RAM来存储您的数据集,而实际上数据本身只占用1.5GB,因为它有0.5GB的口袋。通过执行插入而不是更新可以避免这种碎片。它也可以通过数据库修复来修复。

在MongoDB的下一个版本中,将有一个在线压缩功能。

答案 2 :(得分:1)

  1. 您可以使用嵌入元素
  2. 上的'$ slice'进行分页
  3. 您可以使用“field1.field2”进行搜索:/ aRegex / ,其中aRegex是您搜索的字词。但要注意表现。
  4. 关于3.和4.我没有证明数据。

    BTW 2集合可以更容易编码/使用/管理。您只需在每个“博客”文档中注册blogId,并在所有查询中添加“blogId”:“1234ABCD”