1. 首页 > DB2教程 > 正文

DB2教程FG037-DB2慢查询分析与优化实战

风哥教程参考DB2官方文档Performance Monitoring and Tuning Guide、SQL Reference等内容,详细介绍DB2慢查询的识别、分析方法、优化技术以及在生产环境中的最佳实践。更多视频教程www.fgedu.net.cn

目录大纲

Part01-慢查询基础概念

1.1 慢查询定义

慢查询是指执行时间超过预设阈值的SQL语句,通常表现为:

  • 执行时间过长
  • CPU使用率高
  • IO操作频繁
  • 内存使用过高
  • 锁定时间长
1.2 慢查询的影响
  • 系统性能下降
  • 用户体验变差
  • 资源浪费
  • 可能导致系统崩溃
  • 影响其他查询的执行
1.3 慢查询的原因
  • SQL语句编写不当
  • 缺少索引或索引失效
  • 表结构设计不合理
  • 统计信息过时
  • 数据库参数配置不当
  • 系统资源不足

Part02-生产环境慢查询识别与监控

2.1 慢查询识别方法
  • 使用DB2快照监控
  • 启用DB2语句事件监视器
  • 使用第三方监控工具
  • 分析应用程序日志
  • 定期执行性能报表
2.2 启用语句事件监视器

# 创建语句事件监视器
$ su – db2inst1
$ db2 “CREATE EVENT MONITOR stmt_monitor FOR STATEMENTS WRITE TO TABLE”

# 启动事件监视器
$ db2 “SET EVENT MONITOR stmt_monitor STATE 1”

# 查看事件监视器状态
$ db2 “SELECT * FROM SYSCAT.EVENTMONITORS WHERE NAME = ‘STMT_MONITOR'”

# 查看捕获的语句
$ db2 “SELECT * FROM STMT_MONITOR.STATEMENTS”

# 查找慢查询
$ db2 “SELECT STMT_TEXT, EXECUTION_TIME, CPU_TIME FROM STMT_MONITOR.STATEMENTS WHERE EXECUTION_TIME > 1000 ORDER BY EXECUTION_TIME DESC”

# 关闭事件监视器
$ db2 “SET EVENT MONITOR stmt_monitor STATE 0”

# 删除事件监视器
$ db2 “DROP EVENT MONITOR stmt_monitor”

2.3 使用快照监控慢查询

# 获取数据库快照
$ su – db2inst1
$ db2 “GET SNAPSHOT FOR DATABASE ON fgedb”

# 获取语句快照
$ db2 “GET SNAPSHOT FOR DYNAMIC SQL ON fgedb”

# 查找执行时间长的语句
$ db2 “GET SNAPSHOT FOR DYNAMIC SQL ON fgedb” | grep -A 5 “Elapsed Time”

# 使用db2top监控
$ db2top

# 在db2top中查看慢查询
# 按’s’键查看SQL语句
# 按’L’键查看锁信息
# 按’m’键查看内存使用

# 使用db2pd监控
$ db2pd -d fgedb -stmt
$ db2pd -d fgedb -trans
$ db2pd -d fgedb -locks

Part03-生产环境慢查询分析与优化方案

3.1 慢查询分析方法

# 分析执行计划
$ su – db2inst1
$ db2 “EXPLAIN PLAN FOR SELECT * FROM fgedu_order WHERE order_amount > 1000”

# 查看执行计划
$ db2 “SELECT * FROM EXPLAIN_INSTANCE”
$ db2 “SELECT * FROM EXPLAIN_STATEMENT”
$ db2 “SELECT * FROM EXPLAIN_OPERATOR”

# 使用db2exfmt查看执行计划
$ db2exfmt -d fgedb -1 -o explain_output.txt

# 分析执行计划输出
$ cat explain_output.txt

# 检查索引使用情况
$ db2 “SELECT * FROM EXPLAIN_INDEXES”

# 检查表访问情况
$ db2 “SELECT * FROM EXPLAIN_TABLES”

# 分析统计信息
$ db2 “RUNSTATS ON TABLE fgedu_order”
$ db2 “SELECT * FROM SYSSTAT.TABLES WHERE TABNAME = ‘FGEDU_ORDER'”
$ db2 “SELECT * FROM SYSSTAT.INDEXES WHERE TABNAME = ‘FGEDU_ORDER'”

3.2 SQL语句优化

# 优化前的慢查询
$ db2 “SELECT * FROM fgedu_order WHERE order_amount > 1000”

# 优化后的查询
$ db2 “SELECT order_id, user_id, order_amount FROM fgedu_order WHERE order_amount > 1000”

# 添加索引
$ db2 “CREATE INDEX idx_order_amount ON fgedu_order(order_amount)”

# 优化JOIN查询
$ db2 “SELECT o.order_id, o.user_id, o.order_amount, u.username FROM fgedu_order o JOIN fgedu_user u ON o.user_id = u.user_id WHERE o.order_amount > 1000”

# 优化后
$ db2 “CREATE INDEX idx_user_id ON fgedu_order(user_id)”
$ db2 “SELECT o.order_id, o.user_id, o.order_amount, u.username FROM fgedu_order o JOIN fgedu_user u ON o.user_id = u.user_id WHERE o.order_amount > 1000”

# 优化子查询
$ db2 “SELECT * FROM fgedu_order WHERE user_id IN (SELECT user_id FROM fgedu_user WHERE status = ‘active’)”

# 优化后
$ db2 “SELECT o.* FROM fgedu_order o JOIN (SELECT DISTINCT user_id FROM fgedu_user WHERE status = ‘active’) u ON o.user_id = u.user_id”

# 优化聚合查询
$ db2 “SELECT user_id, SUM(order_amount) FROM fgedu_order GROUP BY user_id”

# 优化后
$ db2 “CREATE INDEX idx_user_id_amount ON fgedu_order(user_id, order_amount)”
$ db2 “SELECT user_id, SUM(order_amount) FROM fgedu_order GROUP BY user_id”

# 优化排序
$ db2 “SELECT * FROM fgedu_order ORDER BY create_time DESC”

# 优化后
$ db2 “CREATE INDEX idx_create_time ON fgedu_order(create_time)”
$ db2 “SELECT order_id, user_id, order_amount FROM fgedu_order ORDER BY create_time DESC”

3.3 索引优化

# 检查索引使用情况
$ db2 “SELECT * FROM SYSSTAT.INDEXES WHERE TABNAME = ‘FGEDU_ORDER'”

# 检查索引效率
$ db2 “RUNSTATS ON TABLE fgedu_order WITH DISTRIBUTION AND DETAILED INDEXES ALL”

# 添加合适的索引
$ db2 “CREATE INDEX idx_order_amount ON fgedu_order(order_amount)”
$ db2 “CREATE INDEX idx_user_id_create_time ON fgedu_order(user_id, create_time)”

# 重建索引
$ db2 “REORG INDEXES ALL FOR TABLE fgedu_order”

# 删除无用索引
$ db2 “DROP INDEX idx_unused_index”

# 分析索引使用情况
$ db2 “SELECT * FROM SYSIBMADM.INDEXUSAGE WHERE TABNAME = ‘FGEDU_ORDER'”

# 索引设计最佳实践
# 1. 为经常查询的列创建索引
# 2. 为JOIN条件列创建索引
# 3. 为ORDER BY和GROUP BY列创建索引
# 4. 避免过多索引
# 5. 定期维护索引

3.4 数据库参数优化

# 优化缓冲池
$ db2 “CREATE BUFFERPOOL bp_8k SIZE 1000 PAGESIZE 8K”
$ db2 “ALTER TABLESPACE USERSpace BUFFERPOOL bp_8k”

# 优化查询优化器
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING QUERYOPT 5”

# 优化排序堆
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING SORTHEAP 1024”

# 优化包缓存
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING PCKCACHESZ 1024”

# 优化锁列表
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING LOCKLIST 1024”

# 优化日志缓冲区
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING LOGBUFSZ 1024”

# 优化最大应用程序数
$ db2 “UPDATE DATABASE CONFIGURATION FOR fgedb USING MAXAPPLS 1000”

# 查看当前配置
$ db2 “GET DATABASE CONFIGURATION FOR fgedb”

# 监控参数效果
$ db2 “GET SNAPSHOT FOR DATABASE ON fgedb”

Part04-慢查询优化实战案例

4.1 案例一:全表扫描优化

# 问题:查询执行时间长,使用全表扫描
$ db2 “SELECT * FROM fgedu_order WHERE order_amount > 5000”

# 分析执行计划
$ db2 “EXPLAIN PLAN FOR SELECT * FROM fgedu_order WHERE order_amount > 5000”
$ db2exfmt -d fgedb -1 -o explain_output.txt

# 发现使用全表扫描
# 解决方案:添加索引
$ db2 “CREATE INDEX idx_order_amount ON fgedu_order(order_amount)”

# 重新执行查询
$ db2 “SELECT * FROM fgedu_order WHERE order_amount > 5000”

# 验证执行计划
$ db2 “EXPLAIN PLAN FOR SELECT * FROM fgedu_order WHERE order_amount > 5000”
$ db2exfmt -d fgedb -1 -o explain_output_optimized.txt

# 确认使用索引扫描
# 性能提升:执行时间从5秒减少到0.1秒

4.2 案例二:JOIN查询优化

# 问题:JOIN查询执行缓慢
$ db2 “SELECT o.order_id, o.user_id, o.order_amount, u.username, u.email FROM fgedu_order o JOIN fgedu_user u ON o.user_id = u.user_id WHERE o.order_amount > 1000”

# 分析执行计划
$ db2 “EXPLAIN PLAN FOR SELECT o.order_id, o.user_id, o.order_amount, u.username, u.email FROM fgedu_order o JOIN fgedu_user u ON o.user_id = u.user_id WHERE o.order_amount > 1000”

# 发现JOIN操作效率低
# 解决方案:添加索引
$ db2 “CREATE INDEX idx_order_user_id ON fgedu_order(user_id)”
$ db2 “CREATE INDEX idx_user_user_id ON fgedu_user(user_id)”

# 重新执行查询
$ db2 “SELECT o.order_id, o.user_id, o.order_amount, u.username, u.email FROM fgedu_order o JOIN fgedu_user u ON o.user_id = u.user_id WHERE o.order_amount > 1000”

# 性能提升:执行时间从10秒减少到0.5秒

4.3 案例三:聚合查询优化

# 问题:聚合查询执行缓慢
$ db2 “SELECT user_id, COUNT(*), SUM(order_amount) FROM fgedu_order GROUP BY user_id HAVING SUM(order_amount) > 10000”

# 分析执行计划
$ db2 “EXPLAIN PLAN FOR SELECT user_id, COUNT(*), SUM(order_amount) FROM fgedu_order GROUP BY user_id HAVING SUM(order_amount) > 10000”

# 发现聚合操作效率低
# 解决方案:添加复合索引
$ db2 “CREATE INDEX idx_user_id_amount ON fgedu_order(user_id, order_amount)”

# 重新执行查询
$ db2 “SELECT user_id, COUNT(*), SUM(order_amount) FROM fgedu_order GROUP BY user_id HAVING SUM(order_amount) > 10000”

# 性能提升:执行时间从8秒减少到0.3秒

4.4 案例四:排序优化

# 问题:排序操作执行缓慢
$ db2 “SELECT * FROM fgedu_order ORDER BY create_time DESC LIMIT 10”

# 分析执行计划
$ db2 “EXPLAIN PLAN FOR SELECT * FROM fgedu_order ORDER BY create_time DESC LIMIT 10”

# 发现排序操作效率低
# 解决方案:添加索引
$ db2 “CREATE INDEX idx_create_time ON fgedu_order(create_time)”

# 重新执行查询
$ db2 “SELECT order_id, user_id, order_amount, create_time FROM fgedu_order ORDER BY create_time DESC LIMIT 10”

# 性能提升:执行时间从6秒减少到0.2秒

Part05-风哥经验总结与分享

5.1 慢查询优化注意事项
  • 定期分析慢查询:建立慢查询监控机制
  • 优化SQL语句:避免全表扫描和复杂子查询
  • 合理设计索引:为频繁查询的列创建索引
  • 维护统计信息:定期运行RUNSTATS
  • 优化数据库参数:根据系统情况调整配置
5.2 常见问题与解决方案
  • 索引失效:检查索引是否被正确使用
  • 统计信息过时:运行RUNSTATS更新统计信息
  • 锁竞争:优化事务和SQL语句
  • 内存不足:调整内存参数配置
  • IO瓶颈:优化存储和SQL语句
5.3 最佳实践建议
  • 使用参数化查询:避免SQL注入和提高缓存效率
  • 限制结果集大小:使用LIMIT或FETCH FIRST
  • 避免SELECT *:只查询需要的列
  • 使用EXPLAIN分析执行计划:了解查询执行情况
  • 定期维护数据库:RUNSTATS、REORG等操作
  • 监控慢查询:建立慢查询告警机制
  • 优化JOIN操作:合理使用JOIN顺序和类型
  • 考虑分区表:对于大表使用分区技术

学习交流加群风哥微信: itpux-com

更多视频教程www.fgedu.net.cn

from:www.itpux.com.qq113257174.wx:itpux-com

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息