【问题标题】:How to efficiently store and update binary data in Mongodb?如何在 Mongodb 中高效地存储和更新二进制数据?
【发布时间】:2017-08-02 17:11:27
【问题描述】:

我在文档中存储了一个大型二进制数组。我希望不断地向这个数组添加字节,并且有时会改变现有字节的值。

我一直在寻找一些 $append_bytes 和 $replace_bytes 类型的修饰符,但似乎我能做的最好的就是 $push 用于数组。如果我能以某种方式访问​​磁盘上的底层 bson,这似乎可以通过执行 seek-write 类型操作来实现,但在我看来,在 mongodb 中无论如何都没有这样做(并且可能有充分的理由)。

如果我只是查询这个二进制数组,对其进行编辑或添加,然后通过重写整个字段来更新文档,这样做的成本会有多高?每个二进制数组的大小约为 1-2MB,每 5 分钟更新一次,涉及 1000 多个文档。更糟糕的是,没有简单的方法可以(及时)将它们分散开,而且它们通常会在 5 分钟的间隔内彼此靠近发生。有没有人对这将是多么灾难性有好感?好像会有问题。

另一种方法是将这些二进制数据作为单独的文件存储在磁盘上,实现一个线程池来有效地操作磁盘上的文件,并从我的 mongodb 文档中引用文件名。 (我正在使用 python 和 pymongo,所以我在看 pytables)。如果可能的话,我宁愿避免这种情况。

我在这里忽略了其他选择吗?

谢谢。

编辑

在为我的用例编写了一些测试之后,我决定为二进制数据对象使用单独的文件系统(特别是使用 pytables 或 h5py 的 hdf5)。除了这些二进制数据对象的持久性之外,我仍然将 mongo 用于所有内容。通过这种方式,我可以将与附加和更新类型操作相关的性能与我的基本 mongo 性能分离。

一位 mongo 开发人员确实指出我可以使用点表示法和 $set 设置内部数组元素(请参阅下面评论中的 ref),但目前无法在数组中原子地执行一系列集合.

此外 - 如果我的 mongo 文档中有 1,000 个 2MB 二进制数据字段并且我经常更新和增长它们(至少每 5 分钟一次) - 我的直觉告诉我 mongo 将不得不管理磁盘上的文件中存在许多分配/增长问题 - 最终这将导致性能问题。我宁愿将其卸载到操作系统级别的单独文件系统来处理。

最后 - 我将使用 numpy 对我的数据进行操作和计算 - pytables 和 h5py 模块都允许在 numpy 行为和存储之间很好地集成。

【问题讨论】:

  • 一位 mongodb 开发人员刚刚引起我的注意,您可以使用带有点符号的 $set 访问单个数组元素。我忽略了这一点。参考在:mongodb.org/display/DOCS/…

标签: mongodb database


【解决方案1】:

正如您所提到的,您经常编辑二进制数据,实际上非常频繁。 GridFS 是我建议的另一个选择。

When to use GridFS 可能对你有用

【讨论】:

  • 我查看了 GridFS ...文件被 put() 到集合中,它负责自动以块的形式分发。似乎如果我需要更改某些内容 - 然后我需要再次 put() - 这会保存另一整组块。它似乎是为不经常更改的版本控制文件而构建的。因此,就我而言,我将拥有大量文件副本。除非它以某种方式通过 diff 存储更改 - 但我看到的文档都没有这样建议......
  • 是的,实际上更新现有的卡盘将是令人难以忍受的头痛。相反,通常您希望遵循以下模式:1.)找到旧的,保留 _id 2.)添加新的 3.)通过 _id 删除旧的
  • 感谢您的参考。我想我可以在 gridfs 中将我的数据分块更小(例如 64KB 块)。然后,当需要进行编辑时——我可以小心地重写受影响的 64KB 块。然后更新整个文件的校验和。我需要做一些工作,但这比让它重写文件的所有块要好得多。感谢您的想法-我可能会研究这种方法。它仍然让我们怀疑我是否要研究 BSON 规范 - 如果我不能直接操作磁盘上受影响的字节。我认为这将是最快的。
  • 祝你好运,但不要忘记发布你找到的解决方案。它也会帮助其他人,我也一样。
猜你喜欢
  • 2019-07-07
  • 2017-08-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 2012-07-30
  • 2014-08-17
相关资源
最近更新 更多