name: mongodb-indexing-optimization version: “2.1.0” description: 掌握MongoDB索引和查询优化。学习索引类型、解释计划、性能调优和查询分析。用于优化慢查询、分析性能或设计索引。 sasmp_version: “1.3.0” bonded_agent: 04-mongodb-performance-indexing bond_type: PRIMARY_BOND
生产级技能配置
capabilities:
- 索引设计
- 解释分析
- 查询优化
- 性能分析
- esr规则应用
input_validation: required_context: - 查询模式 - 集合信息 optional_context: - 解释输出 - 当前索引 - 集合大小
output_format: index_recommendation: 对象 explain_interpretation: 字符串 performance_impact: 字符串 trade_offs: 数组
error_handling: common_errors: - code: IDX001 condition: “解释输出中的COLLSCAN” recovery: “在过滤字段上创建索引,遵循ESR规则” - code: IDX002 condition: “索引未被使用” recovery: “检查查询形状、提示使用或索引前缀” - code: IDX003 condition: “索引过多” recovery: “审查索引使用统计,移除未使用的索引”
prerequisites: mongodb_version: “4.4+” required_knowledge: - 基础查询 - 解释命令 performance_baseline: - “优化前了解当前查询延迟”
testing: unit_test_template: | // 验证索引被使用 const explain = await collection.find(query).explain(‘executionStats’) expect(explain.executionStats.executionStages.stage).toBe(‘IXSCAN’) expect(explain.executionStats.totalDocsExamined).toBeLessThanOrEqual(limit)
MongoDB索引与优化
通过正确的索引掌握性能优化。
快速开始
创建索引
// 单字段索引
await collection.createIndex({ email: 1 });
// 复合索引
await collection.createIndex({ status: 1, createdAt: -1 });
// 唯一索引
await collection.createIndex({ email: 1 }, { unique: true });
// 稀疏索引(跳过空值)
await collection.createIndex({ phone: 1 }, { sparse: true });
// 文本索引(全文搜索)
await collection.createIndex({ title: 'text', description: 'text' });
// TTL索引(自动删除文档)
await collection.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
列出和分析索引
// 列出所有索引
const indexes = await collection.indexes();
console.log(indexes);
// 删除一个索引
await collection.dropIndex('email_1');
// 删除所有非_id索引
await collection.dropIndexes();
解释查询计划
// 分析查询执行
const explain = await collection.find({ email: 'test@example.com' }).explain('executionStats');
console.log(explain.executionStats);
// 显示:executionStages, nReturned, totalDocsExamined, executionTimeMillis
索引类型
单字段索引
// 一个字段上的索引
db.collection.createIndex({ age: 1 })
// 如果搜索年龄,查询使用索引
db.collection.find({ age: { $gte: 18 } })
复合索引
// 多个字段上的索引 - 顺序重要!
db.collection.createIndex({ status: 1, createdAt: -1 })
// 受益的查询:
// 1. { status: 'active', createdAt: { $gt: date } }
// 2. { status: 'active' }
// 但非:单独 { createdAt: { $gt: date } }
数组索引(多键)
// 为数组自动创建
db.collection.createIndex({ tags: 1 })
// 匹配标签包含值的文档
db.collection.find({ tags: 'mongodb' })
文本索引
// 全文搜索
db.collection.createIndex({ title: 'text', body: 'text' })
// 查询
db.collection.find({ $text: { $search: 'mongodb database' } })
地理空间索引
// 2D球面用于经纬度
db.collection.createIndex({ location: '2dsphere' })
// 查找附近
db.collection.find({
location: {
$near: { type: 'Point', coordinates: [-73.97, 40.77] },
$maxDistance: 5000
}
})
索引设计:ESR规则
Equality(相等)、Sort(排序)、Range(范围)
// 查询:查找活跃用户,按创建日期排序,限制年龄
db.users.find({
status: 'active',
age: { $gte: 18 }
}).sort({ createdAt: -1 })
// 最优索引:
db.users.createIndex({
status: 1, // 相等
createdAt: -1, // 排序
age: 1 // 范围
})
性能分析
检查查询是否使用索引
const explain = await collection.find({ email: 'test@example.com' }).explain('executionStats');
// IXSCAN = 好(索引扫描)
// COLLSCAN = 差(集合扫描)
console.log(explain.executionStats.executionStages.stage);
覆盖查询
// 查询结果完全来自索引
db.users.createIndex({ email: 1, name: 1, _id: 1 })
// 这个查询是“覆盖的” - 无需获取文档
db.users.find({ email: 'test@example.com' }, { email: 1, name: 1, _id: 0 })
Python示例
from pymongo import ASCENDING, DESCENDING
# 创建索引
collection.create_index([('email', ASCENDING)], unique=True)
# 复合索引
collection.create_index([('status', ASCENDING), ('createdAt', DESCENDING)])
# 解释计划
explain = collection.find({'email': 'test@example.com'}).explain()
print(explain['executionStats'])
# 删除索引
collection.drop_index('email_1')
最佳实践
✅ 索引用于$match的字段(在管道早期) ✅ 使用ESR规则设计复合索引 ✅ 监控索引大小和内存 ✅ 移除未使用的索引 ✅ 使用explain()验证索引使用 ✅ 索引高基数字符串 ✅ 避免索引许多空值的字段 ✅ 考虑索引交叉 ✅ 定期索引维护 ✅ 监控查询性能