mongodb 5.0+时序集合必须显式创建且不可变更:需用db.createcollection指定timefield(date型)、可选metafield及granularity(seconds/minutes/hours),创建后无法修改;ttl索引须建在{metafield, timefield}复合字段上,聚合需配合$datetrunc匹配granularity才生效。

MongoDB 5.0+ 中必须用 timeseries 集合,而不是手写分桶或单点存储——这不是优化建议,而是底层能力绑定的硬性前提。
创建时序集合必须显式调用 createCollection
往普通集合里插一万条带 ts 字段的文档,它也永远不是时序集合。MongoDB 不会自动识别、升级或转换。
- 必须用
db.createCollection("sensors", { timeseries: { timeField: "ts", metaField: "device", granularity: "minutes" } }) -
timeField必须是Date类型,且每条文档都得有、不能为null或缺失 -
metaField是可选字符串字段(如"device"),用于后续按设备高效分组查询 - 创建后无法修改
timeField、metaField或granularity,也不能把已有集合转成时序集合
granularity 选错会让压缩率暴跌 3–5 倍
它不是“你想查多细就设多细”,而是告诉 MongoDB “同一物理 bucket 里的时间戳大致差多少”。只接受 seconds、minutes、hours 三个值。
- IoT 场景下,若传感器每 30 秒上报一次,却设
granularity: "seconds",MongoDB 会强行按秒切片,产生大量空隙,实测压缩率反而比minutes低 -
minutes更适合温湿度、电表读数等 ≥10 秒间隔、常按小时/天聚合的场景 -
seconds仅当业务真需要亚秒级窗口聚合(如高频金融 tick),且能接受更高磁盘开销 - 注意:
$dateTrunc聚合照常工作,但底层组织方式变了——选错就白用了压缩和分桶能力
TTL 过期必须建 { metaField: 1, timeField: 1 } 复合索引
只在 ts 上建单字段 TTL 索引,清理效率极低:MongoDB 会扫整条时间线,无法按设备粒度推进。
- 正确做法是建复合索引:
db.sensors.createIndex({ device: 1, ts: 1 }, { expireAfterSeconds: 2592000 })(30 天) - 这样过期清理能按设备分批执行,降低单次操作压力
- 补录迟到数据(比如写
2026-04-01的记录)时,该索引仍能准确定位并触发清理
时序集合不支持事务,这点最容易被忽略
如果你的业务流程强依赖跨集合原子性(比如同时写传感器数据 + 更新设备状态),就得在应用层兜底,或改用普通集合 + 分桶设计。
别等到上线才发现——时序集合的优化是垂直的(压缩、分桶、预聚合),但牺牲了横向能力(事务、全文索引、部分更新操作符如 $push 到数组末尾等)。它不是“增强版集合”,而是专用于单一场景的专用结构。











