【问题标题】:MongoDB high storageSizeMongoDB 高存储大小
【发布时间】:2013-12-09 16:51:32
【问题描述】:

我刚刚从 mysql 切换到使用 mongoDB,它非常棒,但我正在努力处理 db 数据大小..

我每天大约有 700 个文档,每个文档里面都嵌入了大约 900 个 cmets。

平均对象大小约为 53k(这只是几个小时),因此通过简单的数学计算,它应该是 53*700 = 37MB。但总大小约为 250MB(storageSize)(仅 2h!)

所以,我每天会创建超过 1GB 的数据,在 mysql 中大约是 100mb/天(甚至更少)。

这正常吗?我该如何处理?谢谢!

【问题讨论】:

  • 您多久使用一次 cmets 更新文档?你用什么运算符?
  • 每分钟嵌入一次,更新和 $push 在 cmets{} 数组中。所以它每分钟大约 700 个嵌入(一天有 1440 分钟,但它不是 24 小时工作的,这就是为什么每个文档大约有 900 个嵌入)。谢谢!
  • 是的,您可能会得到“siwss cheese”效应,基本上是您遭受碎片的困扰,您可以通过运行修复数据库或更改架构以排除 cmets 来解决此问题。
  • 唯一的方法是改变模式,MongoDB 使用单个连续的硬盘空间来存储文档,因此它只有一个硬盘访问来获取它,不幸的是这确实意味着一个不断不断增长的文档会不断移动创建碎片,唯一的解决办法是改变您的应用程序的工作方式
  • 不,应该是超音速的,就像刺猬一样

标签: mysql mongodb database-design database nosql


【解决方案1】:

你看到这个的原因是因为记录对象的碎片化。

MongoDB 中的每个文档都保存在一个内部记录对象中,将其视为代表文档的 C++ 结构。

记录对象是单个连续的硬盘空间块,以限制硬盘查找的次数并使它们连续。但是,这种硬盘查找有一个令人讨厌的缺点,如果您的文档不断增长,那么它们必须不断移动到越来越大的记录对象,将旧记录对象发送到$freelists(内部可用空间列表)被另一个进来的那个大小的对象使用。

这会造成碎片化,我相信这就是您使用自己的数据所看到的。

通常解决此问题的一种方法是使用powerof2sizes (http://docs.mongodb.org/manual/reference/command/collMod/),不幸的是,由于您的文档增加了,我认为这不会起作用。

解决此问题的另一种方法是手动设置填充,以便文档始终适合并且永远不会移动,但您还不能:https://jira.mongodb.org/browse/SERVER-1810

目前,解决此问题的最佳方法是更改​​架构以将 cmets 分解到它们自己的集合中。

这确实意味着两个查询,但它们应该是两个索引超快查询,可能比从磁盘加载该文档慢几微秒。

【讨论】:

  • 那么,为 cmets 创建一个集合并为每个评论创建一个文档?如果每天创建大约 100 万个文档,它会足够快吗?谢谢!
  • @Ksakser 是的,应该是
【解决方案2】:

如果计划更改架构,请访问http://docs.mongodb.org/ecosystem/use-cases/pre-aggregated-reports 以避免数据增长和碎片问题。

【讨论】:

    【解决方案3】:

    我在当前答案中没有看到的一件事是初始插入时的文档填充。您可以通过在开始时用一些额外空间“填充”文档来避免数据增长(在一定程度上),以容纳将来添加的 cmets。

    http://docs.mongodb.org/manual/faq/developers/#faq-developers-manual-padding

    使用您手头已有的关于平均文档大小的数据,在其中添加一点点,并在您的初始插入中包含该填充。它应该可以提高您的更新性能,并避免上述评论者所说的瑞士奶酪效应。

    作为参考,这就是为什么您会看到如此多的额外空间:

    http://docs.mongodb.org/manual/core/record-padding/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2020-09-23
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 2011-11-22
      相关资源
      最近更新 更多