点一下关注吧!!!非常感谢!!持续更新!!!
🚀 AI篇持续更新中!(长期更新)
AI炼丹日志-31- 千呼万唤始出来 GPT-5 发布!"快的模型 + 深度思考模型 + 实时路由",持续打造实用AI工具指南!📐🤖
💻 Java篇正式开启!(300篇)
目前2025年10月13日更新到:
Java-147 深入浅出 MongoDB 分页查询详解:skip() + limit() + sort() 实现高效分页、性能优化与 WriteConcern 写入机制全解析
MyBatis 已完结,Spring 已完结,Nginx已完结,Tomcat已完结,分布式服务正在更新!深入浅出助你打牢基础!
📊 大数据板块已完成多项干货更新(300篇):
包括 Hadoop、Hive、Kafka、Flink、ClickHouse、Elasticsearch 等二十余项核心组件,覆盖离线+实时数仓全栈!
大数据-278 Spark MLib - 基础介绍 机器学习算法 梯度提升树 GBDT案例 详解

慢查询分析
内置分析器
MongoDB提供了内置的查询分析器(profiler),用于监控和记录数据库的读写操作性能。通过db.setProfilingLevel(n,m)
命令可以开启分析器功能,该功能会记录所有CRUD操作以及命令执行的详细信息,包括执行时间、索引使用情况等。
分析器级别设置
-
级别0(关闭分析):
- 用法:
db.setProfilingLevel(0)
- 这是默认设置,不会记录任何操作信息
- 适用于生产环境中不需要监控查询性能的场景
- 用法:
-
级别1(记录慢查询):
- 用法:
db.setProfilingLevel(1, m)
- 其中m单位为毫秒(ms),表示慢查询阈值
- 例如:
db.setProfilingLevel(1, 100)
会记录执行时间超过100ms的操作 - 记录的信息会存储在
system.profile
集合中 - 典型应用场景:生产环境性能调优
- 用法:
-
级别2(记录所有操作):
- 用法:
db.setProfilingLevel(2)
- 会记录所有读写操作,无论执行时间长短
- 会产生大量日志数据,影响性能
- 主要用于开发和测试环境进行全面分析
- 用法:
使用示例
javascript
// 设置记录慢于50ms的查询
db.setProfilingLevel(1, 50)
// 查看当前分析级别
db.getProfilingLevel()
// 查看分析状态详细信息
db.getProfilingStatus()
// 查询记录的分析数据
db.system.profile.find().sort({ts:-1}).limit(10)
注意事项
- 分析记录存储在
system.profile
集合中,这是一个固定大小的集合 - 默认大小为1MB,可以通过
db.createCollection()
修改 - 高级别分析会产生大量数据,可能影响性能
- 建议在生产环境中使用级别1,并设置合理的阈值
- 分析数据包含丰富信息:执行时间、扫描文档数、索引使用情况等
查询监控结果
这个命令用于查询 MongoDB 数据库的性能分析数据,它会返回执行时间最长的 3 个操作记录。具体分析如下:
-
db.system.profile:
- 这是 MongoDB 内置的性能分析集合
- 需要先通过
db.setProfilingLevel(1)
启用性能分析功能才会记录数据 - 默认情况下 profile 集合大小为 1MB
-
find():
- 查询 profile 集合中的所有文档
- 可以添加查询条件,如
find({op: "query"})
只查询查询操作
-
sort({ millis: -1 }):
- 按执行时间(milliseconds)降序排序
-1
表示降序,1
表示升序millis
字段记录了操作执行耗时
-
limit(3):
- 限制返回的记录数为3条
- 通过这个参数可以控制返回的慢查询数量
应用场景:
- 数据库性能调优时,识别耗时最长的操作
- 排查特定时间段内的性能问题
- 监控常规业务操作的执行效率
输出结果包含的重要字段:
ts
:操作时间戳op
:操作类型(query/insert/update/delete)ns
:操作的命名空间(数据库.集合)millis
:操作耗时(毫秒)query
:执行的查询条件planSummary
:查询执行计划
我这里没有慢查询···
数据库性能问题分析
1. 应用程序设计不合理
- 问题表现:应用程序中存在频繁的短连接、未优化的 SQL 查询、大量小事务或 N+1 查询问题。
- 影响:导致数据库连接池耗尽、查询效率低下、事务竞争激烈。
- 示例 :
- 频繁创建和关闭数据库连接,而非使用连接池。
- 未使用批量操作,而是循环执行单条 SQL(如
for
循环插入 1000 条数据)。 - 未合理使用缓存,导致重复查询相同数据。
2. 不正确的数据类型
- 问题表现 :字段类型与实际数据不匹配,如使用
VARCHAR(255)
存储数字,或TEXT
存储短字符串。 - 影响 :
- 存储空间浪费(如
INT
比VARCHAR
更高效)。 - 查询性能下降(如字符串比较比数字比较慢)。
- 索引效率降低(如
LIKE
模糊查询无法有效利用索引)。
- 存储空间浪费(如
- 示例 :
- 使用
DATETIME
存储时间戳,而非更轻量的TIMESTAMP
(如果时间范围允许)。 - 使用
VARCHAR
存储枚举值,而非ENUM
或TINYINT
。
- 使用
3. 硬件配置问题
- 问题表现:数据库服务器 CPU、内存、磁盘 I/O 或网络带宽不足。
- 影响 :
- 查询响应慢,甚至超时。
- 高并发时系统崩溃或频繁卡死。
- 常见场景 :
- 内存不足 :未合理分配缓冲池(如 InnoDB 的
innodb_buffer_pool_size
),导致频繁磁盘读写。 - 磁盘 I/O 瓶颈:使用机械硬盘而非 SSD,或 RAID 配置不合理。
- CPU 过载:复杂查询、全表扫描或未优化的存储过程占用大量 CPU。
- 内存不足 :未合理分配缓冲池(如 InnoDB 的
4. 缺少索引
- 问题表现:频繁执行全表扫描,而非索引扫描。
- 影响:查询速度随数据量增长急剧下降。
- 常见问题 :
- 未对
WHERE
、JOIN
、ORDER BY
或GROUP BY
字段建立索引。 - 索引设计不合理(如单列索引过多,但未使用复合索引)。
- 索引失效(如对索引列使用函数或计算,如
WHERE YEAR(date_column) = 2023
)。
- 未对
- 优化建议 :
- 使用
EXPLAIN
分析查询执行计划,识别缺失的索引。 - 避免过度索引(索引会增加写入开销)。
- 使用
5. 其他常见问题
- 锁竞争:长事务、未提交的事务或行锁升级为表锁,导致并发性能下降。
- 大表未分库分表:单表数据量过大(如千万级),导致查询和维护困难。
- 未定期维护 :如未执行
OPTIMIZE TABLE
或ANALYZE TABLE
,导致统计信息不准确。
通过系统化的分析和优化,可以有效提升数据库性能,避免潜在瓶颈。
EXPLAIN 基础概念
EXPLAIN 是 MySQL 提供的用于分析 SQL 查询执行计划的工具,它能够展示 MySQL 如何执行 SELECT 语句,包括如何使用索引、表连接顺序等重要信息。
EXPLAIN 输出字段详解
1. id 列
- 表示查询中 SELECT 操作的顺序号
- id 越大执行优先级越高
- id 相同则从上往下执行
- id 为 NULL 表示是结果集(如 UNION 结果)
2. select_type 列
- SIMPLE:简单查询(不包含子查询或 UNION)
- PRIMARY:主查询(包含子查询时最外层查询)
- SUBQUERY:子查询(SELECT 或 WHERE 中的子查询)
- DERIVED:派生表(FROM 子句中的子查询)
- UNION:UNION 中的第二个或后续查询
- UNION RESULT:UNION 的结果
3. table 列
- 显示查询涉及的表名
- 可能是表名、派生表名(如 derivedN)或 UNION 结果(如 union1,2)
4. partitions 列
- 显示查询将访问的分区
- 未分区表显示 NULL
5. type 列(重要)
表示表的访问方式,从最好到最差排序:
- system:表只有一行记录(系统表)
- const:通过主键或唯一索引等值查询
- eq_ref:多表连接时使用主键或唯一索引关联
- ref:使用非唯一索引等值查询
- fulltext:全文索引检索
- ref_or_null:类似 ref,但包含 NULL 值查询
- index_merge:索引合并优化
- unique_subquery:IN 子查询使用主键
- index_subquery:IN 子查询使用非唯一索引
- range:索引范围扫描
- index:全索引扫描(索引覆盖)
- ALL:全表扫描(最差情况)
6. possible_keys 列
- 显示可能使用的索引
- 如果为 NULL,表示没有可能的索引
7. key 列
- 实际使用的索引
- 如果为 NULL,表示没有使用索引
8. key_len 列
- 索引使用的字节数
- 可判断索引是否完全使用(复合索引的使用情况)
9. ref 列
- 显示索引的哪一列被使用
- 可能是 const、func 或列名
10. rows 列
- MySQL 预估需要检查的行数
- 重要优化指标(越小越好)
11. filtered 列
- 表示存储引擎返回的数据在 server 层过滤后剩余的比例
- 100% 表示没有过滤
12. Extra 列(重要)
包含额外信息:
- Using index:使用覆盖索引
- Using where:在存储引擎检索后再过滤
- Using temporary:使用临时表
- Using filesort:需要额外排序
- Range checked for each record:没有好索引可用
- Impossible WHERE:WHERE 条件永远为 false
常见优化场景分析
1. 全表扫描(type=ALL)
问题 :没有使用索引
解决方案:
- 为 WHERE 条件列添加合适索引
- 检查索引是否失效(如函数操作导致索引失效)
2. 文件排序(Using filesort)
问题 :ORDER BY 没有使用索引
解决方案:
- 为 ORDER BY 列添加索引
- 创建包含 WHERE 和 ORDER BY 列的复合索引
3. 临时表(Using temporary)
问题 :GROUP BY 或 DISTINCT 操作需要临时表
解决方案:
- 优化 GROUP BY 查询
- 添加合适的索引
4. 索引覆盖(Using index)
良好情况:查询只需要通过索引就能获取所需数据
高级分析技巧
1. 分析复合索引使用
通过 key_len 可以判断复合索引的使用情况:
- 计算每个字段类型占用的字节数
- 比较 key_len 与完整索引长度判断是否部分使用
2. 执行计划可视化
- 使用 MySQL Workbench 可视化执行计划
- 使用 pt-visual-explain 工具生成可视化图表
3. 对比 EXPLAIN 和实际执行
- 使用 EXPLAIN ANALYZE(MySQL 8.0+)获取实际执行统计
- 使用 performance_schema 监控实际查询执行
实战优化案例
案例1:慢查询优化
sql
EXPLAIN SELECT * FROM orders WHERE customer_id = 100 AND status = 'shipped' ORDER BY order_date DESC;
分析:
- 可能缺少 (customer_id, status, order_date) 的复合索引
- 检查 type 是否为 ref 或 range
- 检查 Extra 是否有 Using filesort
案例2:分页查询优化
sql
EXPLAIN SELECT * FROM products LIMIT 10000, 20;
分析:
- 大偏移量分页性能差
- 可优化为基于索引的分页查询
EXPLAIN 格式扩展
MySQL 8.0 支持多种 EXPLAIN 格式:
EXPLAIN FORMAT=TRADITIONAL
:传统表格格式EXPLAIN FORMAT=JSON
:JSON 格式(包含更多细节)EXPLAIN FORMAT=TREE
:树形格式(8.0.16+)
注意事项
- EXPLAIN 不会实际执行查询,只是预测执行计划
- 统计信息可能不准确,导致执行计划与实际不符
- 在优化前后都应使用 EXPLAIN 验证效果
- 复杂查询可能需要结合多种优化手段