首页/数据/NoSQL 速查/部分索引只索引子集
MongoDB99 条

部分索引只索引子集

partialFilterExpression 让索引只覆盖满足条件的文档:空间更小、写放大更低,但查询必须包含兼容条件才能命中。

NoSQL 速查数据更新于 2026-10-13

部分索引只覆盖子集

部分索引通过过滤表达式只索引满足条件的文档:空间更小、写入维护成本更低,但查询必须包含与该条件兼容(更强或相等)的条件才能命中。它特别适合两类需求:一是「唯一约束只对特定状态生效」,二是「绝大多数查询都带同一个筛选条件」。

基本信息

定义createIndex({ email: 1 }, { partialFilterExpression: { status: "active" }, unique: true })
命中前提查询条件必须蕴含过滤表达式(例如同时限定 status 为 active)
典型用途只在有效记录上做唯一约束、减少索引体积与写入放大
查看getIndexes() 的 partialFilterExpression 字段
不支持组合不能与其他特殊索引选项随意叠加,交叉使用时需核对文档
适用版本3.2 及以上

典型使用场景

  • 软删除场景:只对未删除的记录建索引,历史数据不占索引空间
  • 状态约束:同一邮箱允许存在多条历史记录,但有效记录必须唯一
  • 多租户表:只为活跃租户的近期数据建索引,控制索引规模
  • 大字段过滤:只索引有值的那部分文档,减少空值造成的索引膨胀
  • 热点集合瘦身:过滤条件长期固定的查询,用部分索引替代全量复合索引

示例

示例
// 唯一约束只作用于活跃记录:历史记录即使邮箱相同也不冲突
db.users.createIndex(
  { email: 1 },
  { partialFilterExpression: { status: "active" }, unique: true }
)

// 查询必须带上兼容的条件,否则索引不会被采用
db.users.find({ email: "a@example.com", status: "active" }).explain("executionStats")

// 查看索引的过滤表达式,确认与查询条件一致
// db.users.getIndexes().filter(function (ix) { return ix.partialFilterExpression })

命中判断读法

索引过滤条件查询条件是否命中
status = activestatus = active 且有其他条件命中
status = active只按其他字段查询不命中,退回其他索引或扫描
status 属于枚举集合status 取同集合中的单个值命中
不写过滤条件(全量索引)任意条件命中但索引更大、写入更重
用部分索引表达「唯一约束只对特定状态生效」,比全量唯一索引更贴合业务:历史数据与已删除记录不会再与当前有效数据抢同一个唯一位置。
过滤条件与查询条件不满足蕴含关系时,索引会被完全跳过:上线前用 explain 逐个核对核心查询,避免建了索引却没人用。

易错点

  • 过滤表达式与查询条件不一致:查询用不上部分索引,退化为集合扫描而没有任何提示
  • 以为部分索引的唯一约束对所有文档生效:过滤条件之外的文档不受约束,需要业务侧另行保证
  • 把部分索引当通用优化:只有在查询条件相对固定时才划算,条件多样的场景应评估全量复合索引
  • 修改过滤表达式时重建索引:新旧索引并存期间写入放大,需安排窗口并确认影响面

数据来源与参考

  • MongoDB Manual: Partial Indexes
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌