Mongodb课程

第一阶段:MongoDB 基础入门

1.什么是mongodb

MongoDB 是一款开源、跨平台的分布式文档型 NoSQL 数据库 ,由 MongoDB Inc. 公司开发,2007 年首次发布。文档型非关系数据库,用类似 JSON 的结构存储数据

  • 分类:NoSQL(非关系型数据库),区别于 MySQL、Oracle 这类传统关系型数据库(RDBMS),适合互联网业务:用户信息、博客、评论、商品详情
  • 核心存储单元:文档(Document),而非关系库的 "行"
  • 数据格式:基于 BSON(二进制 JSON),兼容 JSON,支持数字、字符串、数组、嵌套对象、日期、二进制等复杂类型

2.对比mysql

MongoDB 概念 MySQL 对应概念 说明
数据库 (Database) 数据库 独立数据仓库
集合 (Collection) 数据表 (table) 存放一批同类文档,无需提前定义表结构
文档 (Document) 行 (row) 一条完整数据,键值对结构
字段 (Field) 列 (column) 文档里的 key
_id 主键 (primary key) 文档唯一标识,自动生成

示例一条文档:

bash 复制代码
{
  "_id": ObjectId("60xxxxx"),
  "name": "张三",
  "age": 22,
  "hobby": ["篮球","编程"],
  "address": {"city":"长沙","district":"雨花区"}
}

3.数据格式bson与ObjectId原理

1、BSON:二进制JSON,是MongoDB数据存储格式,支持更多数据类型(日期、二进制、浮点、ObjectId等)。

2、_id 主键字段:

  • 唯一标识文档,默认自动生成,不可重复

  • ObjectId结构:4字节时间戳+3字节机器ID+2字节进程ID+3字节自增计数器

  • 自带时间属性,可通过_id快速提取文档创建时间

4.客户端工具

bash 复制代码
# 带账号密码
mongosh -u admin -p 123456 --authenticationDatabase admin 127.0.0.1:27017
# 直接指定数据库
mongosh 127.0.0.1:27017/testdb

// 查看所有数据库
show dbs
show databases

// 切换/创建数据库(不存在则自动创建,插入数据后才持久化,隐式创建)
use testdb

// 查看当前所在库
db

// 查看当前库所有集合
show collections
show tables

// 手动创建集合(一般无需手动,插入数据自动生成)
db.createCollection("user")

// 删除集合
db.user.drop()

5.CURD语法

1. 插入文档 insertOne/insertMany

insertOne 插入单条

bash 复制代码
db.user.insertOne({
  name: "张三",
  age: 20,
  hobby: ["篮球", "游戏"],
  addr: { city: "长沙" }
})

insertMany 批量插入多条

bash 复制代码
db.user.insertMany([
  {name:"李四",age:22},
  {name:"王五",age:25}
])

2. 查询 find () /findOne ()

bash 复制代码
// 所有数据
db.user.find()
// 格式化输出(美观)
db.user.find().pretty()

// 查询第一条匹配数据
db.user.findOne({name:"张三"})
// 查询所有匹配的数据
db.user.find({name:"张三"})

条件查询

bash 复制代码
// 等于匹配
db.user.find({name:"张三"})

// 比较运算符
// $gt 大于、$gte大于等于、$lt小于、$lte小于等于、$ne不等于

db.user.find({age: {$gt: 20}})

// 多条件同时满足 and
db.user.find({age:{$gt:18}, name:"李四"})

// $or 或条件
db.user.find({
  $or: [
    {age: {$lt:20}},
    {name:"王五"}
  ]
})

// in 匹配多个值
db.user.find({age: {$in: [20,22,25]}})

投影:只返回指定字段(1 显示,0 隐藏)

bash 复制代码
// 只显示 name、age,隐藏 _id
db.user.find({age:{$gt:18}}, {name:1, age:1, _id:0})

分页、排序、数量

bash 复制代码
// sort 排序:1升序 -1降序
db.user.find().sort({age: -1})

// limit 取前N条
db.user.find().limit(2)

// skip 跳过N条(分页)
db.user.find().skip(1).limit(2)

// 统计总条数
db.user.countDocuments({age: {$gt:18}})

3. 更新 updateOne /updateMany

更新操作必须搭配 $set,否则会覆盖整条文档

bash 复制代码
// updateOne:只更新第一条匹配数据
db.user.updateOne(
  {name:"张三"},
  {$set: {age: 21, sex: "男"}} // 新增/修改字段
)

// updateMany:更新全部匹配数据
db.user.updateMany(
  {age: {$gt:20}},
  {$set: {status: "成年"}}
)

// $inc 数值自增
db.user.updateOne({name:"张三"}, {$inc:{age:1}})

// $push 数组追加元素
db.user.updateOne({name:"张三"}, {$push:{hobby:"跑步"}})

4. 删除 deleteOne /deleteMany

bash 复制代码
// 删除匹配第一条
db.user.deleteOne({name:"张三"})

// 删除所有匹配数据
db.user.deleteMany({age: {$lt:18}})

// 删除集合全部数据
db.user.deleteMany({})

6.索引语法

bash 复制代码
// 创建单字段索引 1升序 -1降序
db.user.createIndex({name:1})

// 复合索引
db.user.createIndex({name:1, age:-1})

// 唯一索引(字段不能重复)
db.user.createIndex({phone:1}, {unique:true})

// 查看集合所有索引
db.user.getIndexes()

// 删除索引
db.user.dropIndex("name_1")

7.聚合查询 aggregate(复杂统计)

管道操作符 $match 过滤、$group 分组、$sort$limit

bash 复制代码
// 统计不同年龄人数
db.user.aggregate([
  // 过滤条件
  {$match: {age: {$gte:18}}},
  // 分组统计
  {$group: {
    _id: "$age", // 分组字段
    total: {$sum: 1} // 计数
  }},
  // 排序
  {$sort: {total:-1}}
])

8.权限 / 用户管理

bash 复制代码
// 切换到admin库
use admin

// 创建管理员用户
db.createUser({
  user: "admin",
  pwd: "123456",
  roles: ["root"]
})

// 创建test只有读权限对数据库testdb
db.createUser({
  user: "test",
  pwd: "123456",
  roles: [{role:"read",db:"testdb"}]
})

// 查看所有用户
db.getUsers()

// 删除用户
db.dropUser("admin")

第二阶段: MongoDB进阶

1.MongoDB 索引底层原理

1. 索引是什么

索引是集合文档中指定字段的有序映射表 ,类似书本目录; 无索引时查询是全集合扫描(COLLSCAN) ,逐条对比文档,数据量大极慢; 有索引时走索引扫描(IXSCAN),直接通过索引定位文档。查看: db.users.getIndexes()

MongoDB 默认索引:_id 唯一索引,自动创建,不可删除。

2. 底层存储结构 B+Tree

  • 内部节点:只存 key,不存储真实数据,用来路由查找;
  • 所有真实数据 / 记录指针只存放在叶子节点
  • 叶子节点形成有序双向链表,范围查询极强。

3. 索引分类底层逻辑

(1)单字段索引

bash 复制代码
db.user.createIndex({age:1})

(2)复合索引(最左前缀匹配原则: 查询条件必须优先使用索引最左侧的字段 ,索引才能正常生效; 一旦中间某个索引字段缺失、或者出现范围查询,该字段右侧所有索引列失效。)

bash 复制代码
db.user.createIndex({name:1,age:1})

(3)唯一索引

bash 复制代码
db.user.createIndex({phone:1},{unique:true})

(4)稀疏索引: 只存储存在该字段的文档,缺失字段不进入索引,节省空间。

bash 复制代码
db.users.createIndex(
    {email:1},
    {sparse:true}
)

(5)文本索引(专门用来全文关键词检索,把字符串内容自动拆分成单词,快速搜索包含某个词语的文档:::: 倒排索引)

bash 复制代码
db.articles.createIndex({ content: "text" })

(6) 地理索引

4. 索引读写代价

索引加速查询,但降低写入性能

  1. 插入 / 更新 / 删除文档时,所有相关索引树必须同步修改;
  2. 索引越多,写操作(insert/update/delete)开销越大;
  3. 索引占用磁盘内存,索引过大无法放入内存时,查询性能暴跌。

5.索引执行计划(判断索引是否生效)

explain("executionStats") 分析执行计划,判断是否命中索引、扫描数据量、执行耗时

bash 复制代码
// 查看查询执行详情
db.user.find({name:"张三",age:22}).explain("executionStats")

关键字段解读:

  1. stage: COLLSCAN:全表扫描,无索引,需要建索引;
  2. stage: IXSCAN:命中索引,正常;

6.索引调优

1.优先将等值条件放在复合索引前面,范围条件放最后

2.遵循最左前缀原则,避免跳跃索引字段查询

3.索引字段上不要使用函数运算

4.控制索引数量,索引越多,写入压力越大。

5.清理无效 / 长期不使用的索引

第三阶段:分布式集群高可用(副本集+分片集群)

1.副本集 Replica Set

1. 副本集作用

  • 故障自动转移,主节点宕机自动选新主,业务无感知;
  • 数据多副本持久化,防止单盘 / 单节点丢失;
  • 读写分离:主写、从读,分摊查询压力;
  • 支持数据回滚、备份恢复。

2. 副本集角色(至少 3 节点标准架构)

(1)Primary 主节点

  • 唯一接收写操作的节点;
  • 所有写入记录 oplog(操作日志),同步给从节点;
  • 一个副本集同一时间只有 1 个主。

(2)Secondary 从节点

  • 异步同步主节点 oplog,保存完整数据副本;
  • 不能写,默认不提供读;可开启 secondaryOk 实现读写分离;
  • 主节点故障时参与投票选举新主。

(3)Arbiter 仲裁节点(可选)

  • 不存数据,只参与投票;
  • 场景:2 个数据节点时,加 1 个仲裁凑奇数,防止脑裂;
  • 生产标准架构:3 个数据节点(1 主 2 从),无需仲裁。

3. 核心机制

3.1 Oplog 同步日志
  • Primary 收到写请求,执行数据写入;
  • 将本次写操作记录写入 oplog.rs
  • Secondary 节点持续异步拉取主节点最新 Oplog;
  • 从节点串行重放日志,保持数据和主节点同步;(从节点追不上主,需重新全量同步)
3.2 自动选举(高可用核心)

选举触发条件:主节点心跳失联(默认 10s) 规则:

  1. 总投票节点必须是奇数,避免平票脑裂;
  2. 候选节点必须拥有最新 oplog(数据最新)才能当选;
  3. 选举期间副本集只读,持续几秒,业务短暂不可写;
  4. 可配置优先级 priority 控制节点优先当选主。
3.3 读写分离模式
bash 复制代码
// mongosh 客户端设置读从节点
db.getMongo().setReadPref("secondaryPreferred")

读策略:

  • primary:只读主(默认,强一致)
  • primaryPreferred:优先主,主挂了读从
  • secondary:只读从(适合报表、离线统计)
  • secondaryPreferred:优先从,无从再读主

4. 副本集故障演示

  1. 主节点宕机 → 2 个从节点检测心跳丢失;
  2. 发起选举,数据最新从节点成为新主;
  3. 应用自动重连新主,业务恢复写入;
  4. 旧主重启后自动变成从,同步缺失 oplog。

2.分片集群 Sharded Cluster(分布式扩容)

当单副本集数据量 TB 级、单库性能瓶颈,使用分片集群水平拆分数据。

1. 分片集群四大组件

1)Shard 分片节点
  • 每一个 Shard 都是独立副本集,自带高可用;
  • 数据按分片键拆分,分散存储在不同 shard;
  • 示例:shard1 (1 主 2 从)、shard2 (1 主 2 从)、shard3 (1 主 2 从)
2)mongos 路由节点
  • 无持久化数据,内存进程;
  • 接收客户端所有 CRUD 请求;
  • 根据分片键路由请求到对应 shard;
  • 聚合、跨分片查询由 mongos 汇总结果;
  • 生产部署多个 mongos 做负载均衡,防止单点故障。
3)Config Server 配置服务器
  • 存储集群元数据:分片信息、分片键、集合路由规则、分片均衡器状态;
  • 必须部署副本集(3 节点),保证元数据高可用;
  • mongos 启动时拉取配置元数据,缓存本地。
4)Balancer 均衡器(后台进程)

运行在 config 服务器,自动监控分片数据块(chunk)分布; 当分片数据差距过大,自动迁移 chunk 到压力小的分片,平衡数据。

2. 分片核心概念:分片键 Shard Key

(1)Chunk 数据块

MongoDB 将集合数据切分成固定大小 chunk(默认 64MB),每个 chunk 只属于一个 shard。

(2)分片键作用

指定集合内 1 个 / 多个字段作为拆分依据,决定数据路由规则。 两种分片策略:

  1. 范围分片:按字段数值区间划分 chunk 例:user_id 1~10000 → shard1;10001~20000 → shard2 适合范围查询,缺点:热点写入(自增 ID 全部写入同一个分片)
  2. 哈希分片:对分片键哈希取模,均匀打散数据到所有分片 解决自增 ID 热点写入,但范围查询性能差
(3) 分片键设计禁忌
  • 低区分度字段(性别、状态)不能做分片键;
  • 频繁更新分片键字段会触发 chunk 迁移,性能暴跌;
  • 分片键一旦选定,无法修改,设计前必须评估业务

3. 分片集群读写流程

  1. 客户端连接 mongos;
  2. mongos 向 config 拉取路由元数据;
  3. 根据查询条件 + 分片键判断数据在哪个 shard;
    • 单分片查询:直接下发对应 shard,性能高;
    • 跨分片查询:mongos 向所有 shard 分发请求,再聚合结果(性能差);
  4. 插入 / 更新 / 删除文档时:路由到对应 shard 副本集主节点;
  5. balancer 后台自动均衡 chunk。

4. 高可用保障机制

  1. 每个 shard 是副本集:单分片节点宕机自动选主,数据不丢;
  2. config 3 节点副本集:元数据多副本,元数据不丢失;
  3. 多 mongos 部署:前端加负载均衡(Nginx/LVS),单个 mongos 挂了不影响业务;
  4. chunk 迁移热迁移:迁移过程不阻塞读写,平衡数据无停机。

3.常见常用运维命令

1.副本集操作

bash 复制代码
// 查看副本集状态
rs.status()
// 查看配置
rs.conf()
// 手动降级主节点(主动切换主)
rs.stepDown()

2.分片集群操作(mongos 中执行)

bash 复制代码
// 查看分片列表
sh.status()
// 开启集合分片
sh.shardCollection("test.user", {shardKey: {userId: "hashed"}})
// 手动触发均衡
sh.startBalancer()
// 查看chunk分布
db.user.getShardDistribution()

第四阶段:运维安全、性能调优、项目实战

一、数据备份与恢复

1.逻辑备份

bash 复制代码
# 指定IP端口、账号密码、指定数据库
mongodump -h 127.0.0.1:27017 -u admin -p 123456 
--authenticationDatabase admin -d testdb -o ./backup_test

#--gzip:压缩备份

# 只备份单个集合
mongodump -d testdb -c user -o ./backup_user

2.逻辑恢复

bash 复制代码
# 恢复指定数据库,带认证
mongorestore -h 127.0.0.1:27017 -u admin -p 123456 --authenticationDatabase admin -d testdb ./backup_test/testdb

# 恢复压缩包
mongorestore --host 127.0.0.1 --port 27017 -u admin -p 123456 --authenticationDatabase admin --gzip ./backup_gz

3.物理备份

直接复制数据目录 /data/db 到备份盘

依赖 LVM 快照、云磁盘快照(阿里云 / 腾讯云磁盘快照)

二、慢查询监控

开启Profiler慢日志、分析慢查询、定位低效语句、优化SQL。

三、存储引擎与参数调优

WiredTiger默认存储引擎原理、缓存配置、内存优化、磁盘IO优化。

四、Python pymongo实战

相关推荐
农村小镇哥1 小时前
Oracle中的锁和10704对高级队列锁
数据库·oracle
峥无1 小时前
SQL性能调优:从执行计划看懂索引的使用与失效
数据库·sql
xyj29175964112 小时前
在Trae中配置数据库MCP
数据库·ai·mcp
廋到被风吹走2 小时前
【AI】【Claude】从 Prompt 到 Agent 的完整进阶地图
数据库·人工智能·prompt
数智化管理手记2 小时前
智能财务能替代人工核算吗?智能财务核心功能包含哪些?
大数据·网络·数据库·数据挖掘·精益工程
金智维科技官方2 小时前
DeepSeek接入企业系统:流程自动化新玩法
大数据·数据库·人工智能
小小龙学IT2 小时前
Tigris:下一代无服务器数据库
数据库·云原生·serverless
凤山老林2 小时前
ORM 框架性能调优:Spring Boot 下 N+1 查询根因治理、动态 SQL 优化与 Fetch 策略实战
数据库·spring boot·sql
laowangpython2 小时前
昆仑通态 Mcgs Pro软件安装步骤(附安装包)Mcgs Pro 3.3.6 下载安装教程(保姆级)
java·服务器·数据库·其他