MongoDB 6.0聚合性能提升需满足严格条件:$sort必须紧接$match后,且二者字段共同构成复合索引前缀;否则仍内存排序。验证需用.explain("executionStats")确认IXSCAN输出有序结果且sortStage.works为0。

MongoDB 6.0 的聚合性能提升不是“自动发生”的,而是依赖你是否写对了 pipeline 结构、建对了索引、选对了视图类型。它不会因为你升级到 6.0 就变快——错的写法在 6.0 里照样慢,甚至更难排查。
为什么 $sort 在 6.0 里可能不走索引?
根本原因不是 MongoDB 不想优化,而是它只在极严格条件下才把 $sort 下推到存储层:必须 $match 紧接 $sort,且二者字段共同构成一个复合索引的前缀。常见错误包括:
-
$match后插了$project或$addFields,哪怕只是加个时间戳字段,下推就失效 - 索引是
{status: 1, createdAt: -1},但$sort写成{createdAt: 1}(方向不一致) -
$match: {createdAt: {$gte: ISODate("...")}}单独存在,没带等值字段,无法构成索引前缀,$sort只能内存排序 - 执行时加了
allowDiskUse: true,部分版本优化器会主动放弃下推判断
验证是否生效,必须用 .explain("executionStats") 查看 executionStages:如果看到 IXSCAN 直接输出有序结果,且 sortStage 的 works 是 0,才算真正下推成功。
物化视图真比普通视图快吗?
快,但只在特定场景下显著。标准视图(db.createView)每次查询都重跑整个 pipeline,底层集合索引能用上,但中间结果全在内存算;而按需物化视图(通过 $out 或 $merge 持久化)把结果存成真实集合,支持独立建索引、字段投影、分片,读取就是普通 find。
- 适合高频访问、计算代价高、数据更新不频繁的报表类场景,比如“每日销售 Top 100 商品”
- 不适合实时性要求高的场景,比如用户个人订单列表——物化视图要手动或定时触发更新,否则数据滞后
- 别在物化视图上建冗余索引:先确认查询模式,再建
{date: 1, category: 1, revenue: -1}这类复合索引,而非单字段堆砌 - 注意磁盘空间和更新锁:一次
$merge可能阻塞对该视图的读,尤其在大集合上
timeSeries 集合的聚簇索引到底加速什么?
只加速基于 timeField 和 metaField 的查询与排序,不是万能加速器。例如你建了个 timeSeries 集合,timeField: "ts",metaField: "device",那以下操作受益:
-
.find({device: "d-001", ts: {$gte: ISODate(...)}}).sort({ts: -1}).limit(1)—— 聚簇物理顺序直接定位,不用额外索引 -
.aggregate([{$match: {device: "d-001"}}, {$sort: {ts: -1}}, {$limit: 5}])—— 排序天然有序,sortStage消失
但如果你查的是 status: "error" 这种非聚簇字段,性能和普通集合一样,必须另建二级索引。而且聚簇索引不能手动开关,也不能用于非 timeSeries 集合——试图对 orders 集合加 {clustered: true} 会报错 unrecognized field 'clustered'。
最容易被忽略的一点:所有这些优化(索引下推、物化视图、聚簇索引)都依赖你主动暴露查询意图。MongoDB 不会猜你想怎么查,它只认 pipeline 的字面结构和索引的字段顺序。写错一个逗号位置,或者漏掉一个等值条件,就退回全量内存排序。



















