首页 / MongoDB 入门教程 / 单字段与复合索引

MongoDB 入门教程

单字段与复合索引

本教程共 50 篇 · 第 41 篇 · 更新于 2026-07-30 · 约 4 分钟阅读

MongoDBMongoDB 入门教程单字段索引复合索引最左前缀ESR规则

41. 单字段与复合索引

本节目标:会建单字段和复合索引,理解最左前缀匹配,并用 ESR 原则排好复合索引的字段顺序。

上一章说了索引为什么快。这一章讲具体怎么建,以及复合索引(Compound Index)的几个关键规则。

41.1 单字段索引

只对单个字段建索引,叫单字段索引(Single Field Index)。语法就是 createIndex({ 字段: 1 })

// 给 products 的 category 建单字段索引
test> db.products.createIndex({ category: 1 })

之后按 category 过滤就能走索引。单字段索引简单,但遇到「又要等值、又要排序、又要范围」的复合查询就不够用了。

41.2 复合索引

复合索引是在多个字段上一起建的索引。字段按顺序组成键。

// 在 city、age 上建复合索引
test> db.users.createIndex({ city: 1, age: 1 })

这个索引先按 city 排序,同 city 内再按 age 排序。它能同时服务「按城市查」「按城市+年龄查」两类查询。

Tip

一个复合索引可以顶多个单字段索引用,省下索引维护成本。别动不动就一个字段建一个索引。

41.3 最左前缀:顺序决定能用哪部分

复合索引遵循最左前缀(Leftmost Prefix)规则:查询必须用到索引的最左连续字段,索引才有效。

上面的 { city: 1, age: 1 } 索引,能支持:

  • { city: "杭州" } ✓ 用了最左字段
  • { city: "杭州", age: 28 } ✓ 用了连续前缀
  • { age: 28 } ✗ 跳过了最左的 city,用不上
// 这条能命中复合索引
test> db.users.find({ city: "杭州", age: { $gt: 25 } }).explain("queryPlanner")
Warning

复合索引里字段顺序很重要。把「等值过滤」的字段放最左,范围或排序字段往后放,才能最大化利用前缀。

41.4 ESR 原则:怎么排字段顺序

面对一个典型查询,字段该怎么排?记住 ESR 三字诀:

  • Equality(等值):先放做精确匹配的字段。
  • Sort(排序):再放做排序的字段。
  • Range(范围):最后放做范围匹配的字段。

例:经常按 city 等值查、按 age 排序、再按 created_at 做范围。索引应建为:

// ESR:city 等值 -> age 排序 -> created_at 范围
test> db.users.createIndex({ city: 1, age: 1, created_at: 1 })
// 完美契合 ESR 的查询
test> db.users.find({ city: "杭州" })
  .sort({ age: 1 })
  .filter({ created_at: { $gte: new Date("2025-01-01") } })
Note

若把范围字段 created_at 放在 age 前面,排序就吃不到索引了,会触发内存排序,性能掉下来。

41.5 索引命名

不指定时,索引名默认是字段和方向用下划线拼起来,比如 city_1_age_1。也可以自己起名:

test> db.users.createIndex(
  { city: 1, age: 1 },
  { name: "idx_city_age" }
)

建好后不能用重命名,只能删了重建。所以起个好懂的名字,后续运维会轻松些。

41.6 小结

单字段索引管一个字段,复合索引管多个。复合索引看最左前缀,字段顺序照 ESR(等值→排序→范围)排,查询才能既走索引又免排序。