MongoDB:索引
目录
1、索引数据结构:B-树
2、索引类型
2.1 单字段索引
2.2 复合索引(最重要!)
2.3 多键索引(数组字段)
2.4 地理空间索引
2.5 全文索引
2.6 哈希索引(分片专用)
2.7 TTL 索引(自动过期)
3、索引管理操作
3.1 创建索引
3.2 查看索引
3.3 删除索引
3.4 修改索引(隐藏/重建)
4、explain分析执行计划
5、慢查询分析
5.1 开启慢查询记录
5.2 慢查询日志分析
1、索引数据结构:B-树
MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进⾏访问,单次查询从结构上来看要快于MySql。
2、索引类型
2.1 单字段索引
// 创建:在 age 字段升序索引
db.users.createIndex({ age: 1 })
-
适用:等值查询、范围扫描(
age: 25
或age: { $gt: 30 }
)
2.2 复合索引(最重要!)
// 创建:先按 city 排序,再按 age 排序
db.users.createIndex({ city: 1, age: -1 })
-
最左前缀原则:
✅ 有效查询:{ city: "北京" }
、{ city: "上海", age: { $lt: 30 } }
❌ 无效查询:{ age: 25 }
(无法命中索引)
2.3 多键索引(数组字段)
// tags 是数组字段:["sports", "music"]
db.products.createIndex({ tags: 1 })
-
行为:为数组中的 每个元素 创建独立索引项
-
限制:复合索引中 最多一个数组字段
2.4 地理空间索引
// 2dsphere 索引(地球球面坐标)
db.places.createIndex({ loc: "2dsphere" })
查询示例:
db.places.find({loc: {$near: {$geometry: { type: "Point", coordinates: [116.4, 39.9] },$maxDistance: 1000 // 1公里内}}
})
2.5 全文索引
db.articles.createIndex({ content: "text" })
-
支持:多语言分词、停用词过滤
-
搜索:
db.articles.find({ $text: { $search: "mongodb tutorial" } })
2.6 哈希索引(分片专用)
db.users.createIndex({ _id: "hashed" }) // 分片键均匀分布
2.7 TTL 索引(自动过期)
// 文档在 create_time 后 3600 秒自动删除
db.logs.createIndex({ create_time: 1 }, { expireAfterSeconds: 3600 })
3、索引管理操作
3.1 创建索引
// 后台构建(不阻塞读写)
db.orders.createIndex({ product_id: 1 }, { background: true })
3.2 查看索引
db.collection.getIndexes()
// 输出:
[{ "v": 2, "key": { "_id": 1 }, "name": "_id_" },{ "v": 2, "key": { "city": 1, "age": -1 }, "name": "city_1_age_-1" }
]
3.3 删除索引
db.users.dropIndex("city_1_age_-1")
3.4 修改索引(隐藏/重建)
// 隐藏索引(测试性能影响)
db.coll.hideIndex("index_name")
// 重建索引(碎片整理)
db.coll.reIndex()
4、explain
分析执行计划
db.orders.find({ user_id: 100 }).explain("executionStats")
注意:索引不是免费的 — 每个索引增加 10-20% 的写入开销。
explain()接收不同的参数,通过设置不同参数我们可以查看更详细的查询计划。
- queryPlanner:queryPlanner是默认参数,具体执行计划信息参考下面的表格。
- executionStats:executionStats会返回执行计划的一些统计信息(有些版本中和allPlansExecution等同)。
- allPlansExecution:allPlansExecution用来获取所有执行计划,结果参数基本与上文相同。
1> queryPlanner默认参数
2> executionStats参数
理想状态:nReturned = totalKeysExamined = totalDocsExamined
stage的类型:
阶段 | 说明 | 优化建议 |
---|---|---|
COLLSCAN | 全集合扫描 | 必须添加索引 |
IXSCAN | 索引扫描 | 检查索引效率 |
FETCH | 文档获取 | 减少回表次数 |
SORT | 内存排序 | 添加排序索引 |
LIMIT | 结果限制 | - |
SKIP | 结果跳过 | 避免大数据集skip |
COUNT_SCAN | 计数扫描 | 高效计数 |
5、慢查询分析
慢查询:
-
定义:执行时间超过设定阈值的操作(默认100ms)
-
范围:包括查询、更新、删除、聚合等所有数据库操作
-
关键指标:执行时间、扫描文档数、返回文档数、索引使用情况
5.1 开启慢查询记录
// 设置慢查询阈值(单位:毫秒)
db.setProfilingLevel(1, { slowms: 50 }) // 查看当前配置
db.getProfilingStatus()
/* 输出:
{"was": 1,"slowms": 50,"sampleRate": 1.0
}
*/
参数 | 默认值 | 说明 | 生产建议 |
---|---|---|---|
slowms | 100 | 慢查询阈值(毫秒) | 50-100ms |
sampleRate | 1.0 | 采样率(1.0=记录所有慢查询) | 0.5(高负载系统) |
profile | 0 | 0=关闭,1=慢查询,2=所有操作 | 1 |
配置文件设置(mongod.conf):
operationProfiling:mode: slowOp # 仅记录慢查询slowOpThresholdMs: 50 # 50ms阈值slowOpSampleRate: 0.5 # 50%采样率
5.2 慢查询日志分析
查看慢查询日志:
// 按执行时间倒序查看
db.system.profile.find().sort({ millis: -1 }).limit(5)
关键日志字段解析:
字段 | 说明 | 优化关注点 |
---|---|---|
op | 操作类型(query/update/remove) | 高频操作类型 |
ns | 命名空间(database.collection) | 热点集合 |
millis | 执行时间(毫秒) | >100ms需优化 |
keysExamined | 扫描索引键数量 | 对比nreturned |
docsExamined | 扫描文档数量 | 过高需索引优化 |
nreturned | 返回文档数量 | 对比keysExamined |
planSummary | 执行计划摘要 | COLLSCAN需警惕 |
command | 完整命令(含查询条件) | 查询模式分析 |
慢查询特征分析:
// 分析不同操作的慢查询分布
db.system.profile.aggregate([{ $group: { _id: "$op", count: { $sum: 1 },avgTime: { $avg: "$millis" },maxTime: { $max: "$millis" }}}
])// 分析TOP慢查询集合
db.system.profile.aggregate([{ $group: { _id: "$ns", count: { $sum: 1 },queries: { $push: { query: "$command", time: "$millis" } }}},{ $sort: { count: -1 } },{ $limit: 3 }
])
之后通过4分析执行计划