Ubuntu环境下MongoDB索引优化方法
为频繁用于查询条件、排序或聚合的字段创建索引,是提升查询性能的核心手段。例如,若经常根据userid字段查询,可执行db.transactions.createIndex({userid: 1})创建单字段索引;对于多字段组合查询(如{field1: value1, field2: value2}),复合索引(db.transactions.createIndex({field1: 1, field2: -1}))能覆盖查询需求,避免创建多个单字段索引。需根据查询模式选择索引类型:文本搜索用文本索引(db.collection.createIndex({content: "text"}))、地理位置查询用地理空间索引(db.collection.createIndex({location: "2dsphere"}))、自动过期数据用TTL索引(db.collection.createIndex({expireAt: 1}, {expireAfterSeconds: 0}))。
复合索引的字段顺序直接影响查询效率,需遵循ESR规则(等值→排序→范围):将等值查询字段放在前面,排序字段次之,范围查询字段最后。例如,查询{a: 1, b: 2, c: {$gte: 1}}.sort({d: 1, e: -1}),最优索引为{a: 1, b: 1, d: 1, e: -1, c: 1}。同时,避免冗余索引(如{a:1,b:1}与{b:1,a:1}只需保留一个)、包含关系的索引(如{a:1,b:1,c:1}可由{b:1,c:1,a:1}覆盖)。
覆盖索引是指查询所需字段均包含在索引中,无需访问原始文档。通过explain("executionStats")查看totalDocsExamined(扫描文档数),若为0则表示查询被索引覆盖。例如,查询{userid: 1}且只需返回userid字段时,添加{userid: 1}索引即可覆盖。需注意排除_id字段(除非显式包含在索引中)。
随着数据增长,索引会逐渐碎片化,需定期重建索引(db.collection.reIndex())以优化存储结构。同时,通过db.collection.stats()监控索引大小(避免超过内存容量),使用db.currentOp()查看索引使用情况,删除未使用或低使用率的索引(db.collection.dropIndex("indexName"))。
使用explain()方法(如db.transactions.find({userid: 1}).explain("executionStats"))分析查询执行计划,重点关注:
winningPlan中的stage是否为IXSCAN,而非COLLSCAN);keysExamined是否远大于nReturned,若是则索引选择性低);SORT阶段,需调整索引顺序以支持排序)。$nin、$not、$mod等操作符时,索引无法生效;COLLSCAN),严重影响性能。通过MongoDB自带工具(如mongostat查看索引操作统计、mongotop查看集合级索引使用时间)或第三方工具(如Percona Monitoring and Management (PMM))监控索引命中率、查询响应时间等指标,及时发现性能瓶颈并调整索引策略。