MongoDB 7.0 复合索引在聚合中仍严格遵循前缀匹配规则,且优化器不再重排 $match 条件适配索引顺序,字段顺序、类型一致性及路径精度必须严丝合缝。
MongoDB 7.0 的复合索引在聚合中仍遵循“前缀匹配”规则,但优化器对阶段的自动前置和字段依赖判断更严格——这意味着旧版本可能“侥幸走索引”的查询,在 7.0 下更容易失效,必须显式按索引顺序组织条件。
复合索引字段顺序在聚合中是否还重要
非常重要,且比 4.4/5.0 更敏感。MongoDB 7.0 的聚合优化器不会为
阶段“重排”查询条件来适配索引顺序。例如你建了索引
:
这个
能用上索引:
这个
无法使用该索引(哪怕字段全在):
—— 缺少最左字段
,且
不是前缀
即使写成
,也不会被重排序去匹配索引,7.0 明确放弃这类启发式尝试
为什么
放在聚合开头也不一定走索引
表面看
在第一阶段,但实际能否命中索引,取决于它是否满足索引前缀 + 查询字段存在性 + 类型一致性。7.0 加强了对隐式类型转换的拦截:
如果字段定义为
,但查询传了
(如
查
字段),7.0 直接跳过索引,而旧版本可能隐式转后扫描
中混合类型(
)会彻底禁用该字段的索引路径
使用
且非前缀匹配(如
)时,7.0 的执行计划明确标记
,表示未进入索引扫描
如何验证聚合是否真正覆盖索引(7.0 新要点)
别只看
里有没有
,要重点检查
和索引键映射:
MongoDB For Windows v3.5.4
MongoDB For Windows v3.5.4
下载
运行带
的聚合,确认
≈
;若前者远大于后者,说明索引没滤掉数据,只是被“扫描”而非“定位”
检查
是否是你期望的复合索引名
注意
:如果它远小于
,说明索引有效;若两者接近,说明几乎全索引扫描,等价于全表扫
7.0 新增
字段,若为
表示有强制索引策略干扰,需排查
容易被忽略的聚合索引陷阱
7.0 对“索引覆盖”的要求更苛刻,尤其在涉及嵌套、数组、通配符时:
后的
无法复用原始文档字段的复合索引,必须为展开后的路径单独建索引(如
)
复合索引
不能用于查询
,即使
是同一对象——7.0 不再尝试字段共祖推断
使用
时,若中间结果超出内存限制,索引在后续阶段(如
)完全失效,此时
必须靠
前的独立索引支撑
真正关键的不是“有没有索引”,而是“聚合每一步是否在索引定义的字段顺序、类型、路径精度上严丝合缝”。7.0 把模糊地带收窄了,代价是调试时得一行行核对
输出里的
和实际查询字段。
$match$match{ user_id: 1, order_date: 1, status: 1 }$match{ user_id: ObjectId("..."), order_date: { $gte: ... } }$match{ order_date: { $gte: ... }, status: 1 }user_idorder_date{ status: 1, user_id: ... }$match$matchStringNumber{ "age": 25 }String$in[123, "123"]$regex/abc$/"indexBounds": []explain("queryPlanner")"stage": "IXSCAN"executionStatsexplain("executionStats")docsExaminednReturnedexecutionStats.executionStages.inputStage.indexNameexecutionStats.executionStages.inputStage.keysExamineddocsExaminedindexFilterSettruedb.runCommand({planCacheSetFilter: ...})$unwind$match"items.price": 1{ a: 1, "b.c": 1 }{ "b.d": 1 }ballowDiskUse: true$group$sort$groupexplainindexKeyPattern