什么是MongoDB索引?¶
在MongoDB中,索引就像一本书的“目录”——没有目录时,你得翻遍全书找内容;有了目录,就能快速定位到目标内容。索引的核心作用是加速查询,避免全表扫描(即遍历整个集合),让查询更快更高效。
为什么需要建索引?¶
想象你有一个存了100万条用户数据的集合,要找“年龄=25岁”的用户。如果没有索引,MongoDB会逐条检查每条数据,可能要扫描几十万条;但如果给age字段建了索引,MongoDB就会直接通过索引定位到所有年龄为25岁的文档,效率瞬间提升。
单字段索引:最简单的索引类型¶
单字段索引是给单个字段建立的索引,是最基础也最常用的索引类型。
适用场景¶
- 当查询条件只涉及一个字段(如
name、age)。 - 当需要按单个字段排序(如按
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(第三个字段,降序)。
索引的“坑”:别让索引变成负担¶
索引不是越多越好,过度索引会影响写入性能(插入、更新、删除时需维护索引)。需要注意:
- 避免重复索引:比如给同一个字段建多个索引(如
{age:1}和{age:-1}),只会浪费空间且无法同时生效。 - 低选择性字段少建索引:如果字段值重复率高(如“性别”只有男/女),建索引效果有限,甚至不如全表扫描。
- 只对高频查询建索引:比如每天查询100次的字段值得建索引,偶尔查询的字段没必要。
总结¶
- 单字段索引:适合单字段过滤/排序,语法简单,是基础。
- 复合索引:适合多字段过滤+排序,核心是左前缀原则(仅用最左侧字段的查询能触发索引)。
- 关键原则:索引要“按需建、适度建”,用在高频查询场景,避免影响写入效率。
如果数据量大且查询复杂,复合索引能显著提升性能;但记住:索引是为了加速查询,不是“万能药”,合理规划才能让MongoDB跑得更快~