MongoDB索引类型:单字段、复合索引怎么建?

什么是MongoDB索引?

在MongoDB中,索引就像一本书的“目录”——没有目录时,你得翻遍全书找内容;有了目录,就能快速定位到目标内容。索引的核心作用是加速查询,避免全表扫描(即遍历整个集合),让查询更快更高效。

为什么需要建索引?

想象你有一个存了100万条用户数据的集合,要找“年龄=25岁”的用户。如果没有索引,MongoDB会逐条检查每条数据,可能要扫描几十万条;但如果给age字段建了索引,MongoDB就会直接通过索引定位到所有年龄为25岁的文档,效率瞬间提升。

单字段索引:最简单的索引类型

单字段索引是给单个字段建立的索引,是最基础也最常用的索引类型。

适用场景

  • 当查询条件只涉及一个字段(如nameage)。
  • 当需要按单个字段排序(如按reg_time降序查最新注册用户)。

创建语法

db.集合名.createIndex({字段名: 1})  // 1表示升序,-1表示降序

例子

假设我们有一个“学生表”集合students,经常需要查询“年龄为20岁的学生”,可以这样建索引:

// 给age字段建升序索引
db.students.createIndex({age: 1})  

// 查询时,MongoDB会自动使用age索引
db.students.find({age: 20}).explain("executionStats")  

注意

  • 升序(1)和降序(-1)的选择取决于查询需求。比如按年龄倒序查学生,建{age: -1}更合适。
  • 单字段索引仅能优化包含该字段的查询。例如,给age建索引后,只有find({age: x})能用上索引,find({name: "小明"})无法使用这个索引。

复合索引:同时优化多个字段的查询

复合索引是给多个字段组合建立的索引,适合需要同时过滤或排序多个字段的场景(如“按地区+注册时间”查用户)。

核心原则:左前缀原则

复合索引的顺序非常关键!MongoDB会按照索引定义的字段顺序(左到右)生效,只有包含索引最左侧的字段的查询,才能用上整个复合索引。

例子1:正确使用复合索引

假设我们建了{region: 1, reg_time: -1}的复合索引(先按地区升序,再按注册时间降序):
- ✅ 能用索引的查询:find({region: "北京", reg_time: {$gt: ISODate("2023-01-01")}})(先过滤地区,再过滤注册时间)。
- ❌ 不能用索引的查询:find({reg_time: {$gt: ISODate("2023-01-01")}})(缺少最左侧字段region,无法触发左前缀原则)。

例子2:顺序反了会怎样?

如果建了{reg_time: -1, region: 1}的复合索引(先按注册时间降序,再按地区升序):
- ✅ 能用索引的查询:find({reg_time: {$gt: ISODate("2023-01-01")}})(仅用reg_time)或find({reg_time: {$gt: ISODate("2023-01-01"), region: "北京"}})
- ❌ 无法用索引的查询:find({region: "北京"})(缺少最左侧字段reg_time)。

创建语法

db.集合名.createIndex({字段1: 1, 字段2: -1})  // 逗号分隔,1升序,-1降序

例子:电商订单查询

假设我们有orders集合,经常需要查询“地区=上海+订单状态=已支付”的订单,且按“下单时间”降序排序。此时可以建复合索引:

db.orders.createIndex({region: 1, status: 1, order_time: -1})  

这个索引能同时优化:
- 过滤条件:region: "上海"(最左侧字段)、status: "已支付"(第二个字段)。
- 排序条件:order_time: -1(第三个字段,降序)。

索引的“坑”:别让索引变成负担

索引不是越多越好,过度索引会影响写入性能(插入、更新、删除时需维护索引)。需要注意:

  1. 避免重复索引:比如给同一个字段建多个索引(如{age:1}{age:-1}),只会浪费空间且无法同时生效。
  2. 低选择性字段少建索引:如果字段值重复率高(如“性别”只有男/女),建索引效果有限,甚至不如全表扫描。
  3. 只对高频查询建索引:比如每天查询100次的字段值得建索引,偶尔查询的字段没必要。

总结

  • 单字段索引:适合单字段过滤/排序,语法简单,是基础。
  • 复合索引:适合多字段过滤+排序,核心是左前缀原则(仅用最左侧字段的查询能触发索引)。
  • 关键原则:索引要“按需建、适度建”,用在高频查询场景,避免影响写入效率。

如果数据量大且查询复杂,复合索引能显著提升性能;但记住:索引是为了加速查询,不是“万能药”,合理规划才能让MongoDB跑得更快~

小夜