索引是MongoDB查询性能的核心保障,设计时需结合查询模式与数据特征,遵循以下黄金法则:
user_id、mobile)创建索引,避免为低选择性字段(如gender)浪费资源;db.users.find({age: {$gt: 18}}, {name: 1, age: 1, _id: 0})可通过索引完成);db.orders.createIndex({status: 1, orderDate: -1, amount: 1}),其中status为等值查询、orderDate为排序、amount为范围查询);复合索引是提升多字段查询效率的关键,需根据查询场景设计字段顺序:
db.users.find({username: "admin", email: "admin@example.com"}).sort({createTime: -1}),复合索引{username: 1, email: 1, createTime: -1}可完全覆盖);{a: 1, b: 1},则无需单独创建{a: 1}(除非有特殊查询需求);_id: 0排除默认返回的_id字段,进一步减少IO。根据业务需求创建特殊类型索引,解决特定问题:
db.users.createIndex({username: 1}, {partialFilterExpression: {active: true}}),仅索引活跃用户);db.logs.createIndex({createdAt: 1}, {expireAfterSeconds: 86400}),7天后自动删除过期日志);db.places.createIndex({location: "2dsphere"}),用于“附近地点”查询)。通过explain()方法分析查询执行计划,识别索引使用问题:
winningPlan.stage:若为COLLSCAN(全表扫描),说明未使用索引;executionStats.totalKeysExamined:索引键检查数,数值过大表示索引效率低;executionStats.totalDocsExamined:文档检查数,若远大于返回结果数,说明索引未覆盖查询;executionStats.executionTimeMillis:执行时间,超过100ms需优化;explain()结果添加缺失索引、调整复合索引顺序或修改查询条件(如将$or查询改为$in查询,避免全表扫描)。db.collection.aggregate([{ $indexStats: {} }])查看索引使用情况);$ne、$not、$nin等操作符通常会导致全表扫描,尽量避免在查询中使用;/abc/),若需使用正则,尽量采用左锚定(如/^prefix/),以便利用索引;mongostat(监控操作速率)、mongotop(监控集合级IO)或第三方工具(如Percona PMM)实时监控索引使用情况;db.collection.reIndex()重建碎片化索引,保持索引性能(建议在低峰期操作);