Mongoose 查询性能怎么优化?
Mongoose 性能优化核心三板斧:.lean() 返回纯 JS 对象跳过文档 hydrated 过程提速 5-10 倍;.select() 投影只取需要的字段减少传输;合理建索引覆盖高频查询。三者组合使用效果最显著,读多写少的场景优先考虑 lean。
追问
.lean() 具体省掉了什么? Mongoose 默认将查询结果包装为 Document 实例,附带 change tracking、虚拟字段、方法等。lean() 跳过这些直接返回 POJO,丧失 save()、modify 等实例能力,但只读场景下性能提升显著。
复合索引的 ESR 规则是什么? Equality → Sort → Range,索引字段按等值查询、排序、范围查询的顺序排列,让 MongoDB 最大化利用索引。如 { status: 1, createdAt: -1, age: 1 } 覆盖 WHERE status=? ORDER BY createdAt DESC WHERE age>?
批量操作用什么 API? insertMany 批量插入、updateMany 批量更新、deleteMany 批量删除。单条循环操作每次都有网络往返,批量 API 一次请求完成,数量大时差距可达 10 倍以上。
连接池怎么配? mongoose.connect uri 中设置 maxPoolSize(默认 100)和 minPoolSize。高并发短请求场景适当增大池,长连接场景注意 socketTimeoutMS 避免连接假死。连接应在应用启动时建立并复用,禁止请求内创建。
为什么不建议滥用 populate? populate 每个引用字段都是一次额外查询,列表页查 20 条记录 populate 一个字段就变成 21 次查询。替代方案:$lookup 聚合在数据库端完成关联,或冗余存储常用字段减少关联需求。
写段代码
javascript// lean + select + 索引 三板斧 userSchema.index({ status: 1, createdAt: -1 }); const users = await User .find({ status: 'active' }) .select('name email') .lean(); // 批量插入替代循环 await User.insertMany(usersToInsert);