MongoDB:索引

目录

1、索引数据结构:B-树

2、索引类型

[2.1 单字段索引](#2.1 单字段索引)

[2.2 复合索引(最重要!)](#2.2 复合索引(最重要!))

[2.3 多键索引(数组字段)](#2.3 多键索引(数组字段))

[2.4 地理空间索引](#2.4 地理空间索引)

[2.5 全文索引](#2.5 全文索引)

[2.6 哈希索引(分片专用)](#2.6 哈希索引(分片专用))

[2.7 TTL 索引(自动过期)](#2.7 TTL 索引(自动过期))

3、索引管理操作

[3.1 创建索引](#3.1 创建索引)

[3.2 查看索引](#3.2 查看索引)

[3.3 删除索引](#3.3 删除索引)

[3.4 修改索引(隐藏/重建)](#3.4 修改索引(隐藏/重建))

4、explain分析执行计划

5、慢查询分析

[5.1 开启慢查询记录](#5.1 开启慢查询记录)

[5.2 慢查询日志分析](#5.2 慢查询日志分析)


1、索引数据结构:B-树

MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进⾏访问,单次查询从结构上来看要快于MySql。

2、索引类型

2.1 单字段索引

javascript 复制代码
// 创建:在 age 字段升序索引
db.users.createIndex({ age: 1 }) 
  • 适用:等值查询、范围扫描(age: 25age: { $gt: 30 }

2.2 复合索引(最重要!)

javascript 复制代码
// 创建:先按 city 排序,再按 age 排序
db.users.createIndex({ city: 1, age: -1 })
  • 最左前缀原则

    ✅ 有效查询:{ city: "北京" }{ city: "上海", age: { $lt: 30 } }

    ❌ 无效查询:{ age: 25 }(无法命中索引)

2.3 多键索引(数组字段)

javascript 复制代码
// tags 是数组字段:["sports", "music"]
db.products.createIndex({ tags: 1 })
  • 行为:为数组中的 每个元素 创建独立索引项

  • 限制:复合索引中 最多一个数组字段

2.4 地理空间索引

javascript 复制代码
// 2dsphere 索引(地球球面坐标)
db.places.createIndex({ loc: "2dsphere" })

查询示例:

javascript 复制代码
db.places.find({
  loc: {
    $near: {
      $geometry: { type: "Point", coordinates: [116.4, 39.9] },
      $maxDistance: 1000 // 1公里内
    }
  }
})

2.5 全文索引

javascript 复制代码
db.articles.createIndex({ content: "text" })
  • 支持:多语言分词、停用词过滤

  • 搜索:db.articles.find({ $text: { $search: "mongodb tutorial" } })

2.6 哈希索引(分片专用)

javascript 复制代码
db.users.createIndex({ _id: "hashed" }) // 分片键均匀分布

2.7 TTL 索引(自动过期)

javascript 复制代码
// 文档在 create_time 后 3600 秒自动删除
db.logs.createIndex({ create_time: 1 }, { expireAfterSeconds: 3600 })
复制代码

3、索引管理操作

3.1 创建索引

javascript 复制代码
// 后台构建(不阻塞读写)
db.orders.createIndex({ product_id: 1 }, { background: true })

3.2 查看索引

javascript 复制代码
db.collection.getIndexes()
// 输出:
[
  { "v": 2, "key": { "_id": 1 }, "name": "_id_" },
  { "v": 2, "key": { "city": 1, "age": -1 }, "name": "city_1_age_-1" }
]

3.3 删除索引

javascript 复制代码
db.users.dropIndex("city_1_age_-1")

3.4 修改索引(隐藏/重建)

javascript 复制代码
// 隐藏索引(测试性能影响)
db.coll.hideIndex("index_name")
// 重建索引(碎片整理)
db.coll.reIndex()

4、explain分析执行计划

javascript 复制代码
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 开启慢查询记录

javascript 复制代码
// 设置慢查询阈值(单位:毫秒)
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):

bash 复制代码
operationProfiling:
  mode: slowOp               # 仅记录慢查询
  slowOpThresholdMs: 50      # 50ms阈值
  slowOpSampleRate: 0.5      # 50%采样率

5.2 慢查询日志分析

查看慢查询日志:

javascript 复制代码
// 按执行时间倒序查看
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 完整命令(含查询条件) 查询模式分析

慢查询特征分析:

javascript 复制代码
// 分析不同操作的慢查询分布
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分析执行计划

相关推荐
没有bug.的程序员34 分钟前
MyBatis 初识:框架定位与核心原理——SQL 自由掌控的艺术
java·数据库·sql·mybatis
Databend1 小时前
Databend 亮相 DTCC 2025:存算分离架构引领湖仓一体化
数据库
回家路上绕了弯1 小时前
ClickHouse 深度解析:从核心特性到实战应用,解锁 OLAP 领域新势能
数据库·后端
张铁铁是个小胖子1 小时前
mysql是怎样运行的(梳理)
数据库·mysql
猫猫的小茶馆2 小时前
【STM32】CubeMX(十三):RT-THREAD
stm32·单片机·嵌入式硬件·mcu·mongodb·51单片机·智能硬件
许泽宇的技术分享3 小时前
当自然语言遇上数据库:Text2Sql.Net的MCP革命如何重新定义开发者与数据的交互方式
数据库·.net·text2sql·mcp
2301_803554523 小时前
redis学习
数据库·redis·学习
TT哇4 小时前
@[TOC](MySQL)MySQL经典练习题(详解)
数据库·mysql
Yichen_liuuil4 小时前
Oracle数据库迁移
数据库·oracle·备份·迁移
小李飞刀李寻欢4 小时前
MongoDB /redis/mysql 界面化的数据查看页面App
redis·mysql·mongodb