首页 > 解决方案 > MongoDB Bucket upsert 性能

问题描述

TL;DR: 我对桶模型的 upserts 比以更细粒度格式插入相同文档慢 10 倍。

背景: 我们将物联网数据存储在 PSS MongoDB 副本集中。目前,我们有一个小型模型,可以将每个传感器值保存在一个文档中,格式如下:

{
  _id: <ObjectId>,
  Time: <DateTime>,
  Value: <Object>,
  InternalId: <string>
}

使用我们当前的服务器(512GB RAM,64 个线程,NVMe 磁盘),我们观察到每秒 20 万次以上的读/写,加起来。文档平均大小为 120 字节,7 天数据总计 80 亿个文档,消耗大约 1TB 的存储空间。

我们现在正在转向存储桶模型以提高存储效率。目前,我正在使用以下建议的模型:

{
  _id: <ObjectId>,
  BlockStartTime: <DateTime>,
  BlockEndTime: <DateTime>,
  InternalId: <String>,
  LastModified: <DateTime>,
  Telemetry: [
    Key: <DateTime>,
    Value: <Object>,
    ...
  ]
}

该模型在 RAM 使用和存储方面非常有效。但是,所有写入都非常慢。我使用以下内容插入遥测记录:

db.Telemetry.BulkWrite([
    {
        updateOne: {
            filter: { InternalId: <Guid>, BlockStartTime: <DateTime>},
            update: {
                $currentDate: { LastModified: true },
                $setOnInsert: { BlockEndTime: <DateTime>},
                $push: { Telemetry: { $each: [{ Key: <DateTime>, Value: <Object>}] }}
            },
            upsert: true
        }
]

上面的 BulkWrite 通常包含 25 - 775 个查询,几乎总是包含一个键值对以插入“遥测”。

性能已从 100K+ 写入/秒下降到 5k/s - 10k/s 更新。

我尝试了以下方法:

我的问题: upsert 是数据摄取的方式吗?我可以理解性能下降 50%(upsert 需要查找,然后更新或插入),但是 10 倍下降正常吗?我的摄取策略是否遗漏了什么?我是否应该尝试仅以存储桶格式存储作为汇总策略,可能在摄取后一小时?我们需要为这个客户端使用 MongoDB

标签: mongodbmongodb-query

解决方案


推荐阅读