跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

MongoDB 7.0如何优化复合索引聚合_对比旧版本观察索引覆盖查询变化

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

相关文章