从性能角度来看 MongoDB 嵌入式与参考
Posted
技术标签:
【中文标题】从性能角度来看 MongoDB 嵌入式与参考【英文标题】:MongoDB embedded vs. reference from performance perspective 【发布时间】:2011-09-14 18:32:32 【问题描述】:我读到从性能的角度来看嵌入更好: “如果性能是一个问题,嵌入。” (http://www.mongodb.org/display/DOCS/Schema+Design) 并且大多数指南总是说应该嵌入包含。
但是我不确定情况是否如此。假设我们有两个对象:Blog 和 Post。博客包含帖子。
现在将所有帖子嵌入到博客中会出现以下问题:
-
分页。由于无法过滤嵌入对象,我们将始终获取所有帖子并需要在应用程序中将它们过滤掉。
过滤。和以前一样,在帖子中搜索单词时,将无法从 MongoDB 中过滤嵌入的集合。
插入。我假设插入集合比插入嵌入对象更快。它是否正确?这是写在哪里?
更新。和以前一样,小文档(帖子)内的内联更新字段可能比博客大文档内的内联更新更快。这是正确的吗?
考虑到以上所有内容,我会在一个单独的集合中发布引用博客的帖子。这是正确的结论吗?
(注意:请不要在回复中考虑文档大小限制,假设每个博客最多有 1000 个帖子)
【问题讨论】:
【参考方案1】: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 |
---------------------------------------------------------------
【讨论】:
感谢您的详细解答。 您确定 #2 返回的博客包含一篇与标题匹配的帖子吗?我认为它会返回包含“Mongodb!”的帖子的博客。标题。然后 slice 只会过滤第一个帖子。所以你会得到不正确的帖子 见这里:***.com/questions/2138454/… @mbdev: #2 只是有假查询。我只是向您展示如何做到这一点。 @Andrew 你检查过我发布的链接吗?【参考方案2】:至于 3 & 4,如果是插入到嵌套文档中,基本上就是更新了。
这可能对您的性能非常不利,因为插入通常会附加到数据的末尾,这样可以正常且快速地工作。另一方面,更新可能要复杂得多。
如果您的更新没有改变文档的大小(意味着您有一个键\值对并且只是将值更改为占用相同空间量的新值)那么您会没事的,但是当您开始修改文档并添加新数据,出现问题。
问题在于,虽然 MongoDB 为每个文档分配的空间超过了它所需的空间,但这可能还不够。如果您插入一个 1k 大的文档,MongoDB 可能会为该文档分配 1.5k,以确保对文档的微小更改有足够的空间来增长。如果您使用的空间超过分配的空间,MongoDB 必须获取整个文档并在数据的尾部重新写入。
在获取和重写数据时显然会影响性能,这种操作的频率会放大数据。更糟糕的是,当这种情况发生时,您最终会在数据文件中留下未使用空间的漏洞或口袋。
这最终会被复制到内存中,这意味着您最终可能会使用 2GB 的 RAM 来存储您的数据集,而实际上数据本身只占用 1.5GB,因为有 0.5GB 的存储空间。这种碎片可以通过插入而不是更新来避免。它也可以通过进行数据库修复来修复。
在 MongoDB 的下一个版本中,将会有一个在线压缩功能。
【讨论】:
你认为这些数字会比 Andrew 的数字更糟吗? 不可能说 - 我 100% 取决于您的数据结构以及文档和嵌入文档的大小。一旦您尝试插入大于分配的可用空间的文档,您将看到写入性能下降。我认为这很难用相对较小数据集的小测试来证明。【参考方案3】:-
您可以在嵌入元素上使用 '$slice' 进行分页
您可以使用 "field1.field2": /aRegex/ 进行搜索,其中 aRegex 是您搜索的单词。但要注意性能。
关于 3. 和 4. 我没有证据数据。
BTW 2 集合可以更容易编码/使用/管理。您可以简单地在每个“博客”文档中注册 blogId 并在所有查询中添加 "blogId":"1234ABCD"
【讨论】:
以上是关于从性能角度来看 MongoDB 嵌入式与参考的主要内容,如果未能解决你的问题,请参考以下文章