1. 首页 > 国产数据库教程 > TiDB教程 > 正文

tidb教程FG024-TiDB执行计划与SQL优化

本文档详细介绍TiDB执行计划与SQL优化方法,包括执行计划概念、组件、类型、分析、SQL优化策略、实施方案、实战案例等内容。风哥教程参考TiDB官方文档执行计划相关内容,适合DBA和开发人员在日常使用TiDB时参考。更多视频教程www.fgedu.net.cn

Part01-基础概念与理论知识

1.1 执行计划概念

执行计划是数据库优化器生成的查询执行方案,用于指导SQL语句的执行。

  • 定义:数据库优化器根据SQL语句和统计信息生成的执行方案
  • 作用:指导SQL语句的执行,影响查询性能
  • 生成过程:优化器分析SQL语句,评估不同执行方案的成本,选择最优方案
执行计划的重要性:

  • 了解SQL语句的执行方式
  • 识别性能瓶颈
  • 优化查询性能
  • 验证索引使用情况

1.2 执行计划组件

TiDB执行计划包含以下主要组件:

1.2.1 访问类型(Access Type)

# 访问类型
– ALL:全表扫描
– index:索引扫描
– range:范围扫描
– ref:非唯一索引扫描
– eq_ref:唯一索引扫描
– const:常量扫描
– system:系统表扫描
– NULL:不需要访问表

1.2.2 索引使用(Key)

# 索引使用
– PRIMARY:使用主键索引
– idx_name:使用名为idx_name的索引
– NULL:未使用索引

1.2.3 行估计(Rows)

# 行估计
– 估计扫描的行数
– 影响执行计划的选择
– 基于统计信息计算

1.2.4 额外信息(Extra)

风哥提示:
# 额外信息
– Using index:使用覆盖索引
– Using where:使用WHERE条件过滤
– Using temporary:使用临时表
– Using filesort:使用文件排序
– Using join buffer:使用连接缓冲区
– Using index condition:使用索引条件下推

1.3 执行计划类型

# 执行计划类型

## 1. 表扫描
– 全表扫描:扫描整个表
– 索引扫描:扫描索引
– 范围扫描:扫描索引的特定范围

## 2. 连接类型
– Nested Loop Join:嵌套循环连接
– Hash Join:哈希连接
– Merge Join:合并连接

## 3. 排序操作
– Using filesort:使用文件排序
– Using index:使用索引排序

## 4. 聚合操作
– Using temporary:使用临时表
– Using index:使用索引聚合

## 5. 子查询处理
– 相关子查询:依赖外部查询
– 非相关子查询:独立于外部查询

风哥提示:了解执行计划的组件和类型有助于分析和优化SQL语句。学习交流加群风哥微信: itpux-com

Part02-生产环境规划与建议

2.1 执行计划分析

2.1.1 使用EXPLAIN分析执行计划

# 使用EXPLAIN分析执行计划

## 1. 基本语法
EXPLAIN SELECT * FROM fgedu_users WHERE name = ‘张三’;

## 2. 查看详细执行计划
EXPLAIN ANALYZE SELECT * FROM fgedu_users WHERE name = ‘张三’;

## 3. 分析执行计划输出
– id:执行计划的唯一标识
– select_type:查询类型
– table:表名
– type:访问类型
– possible_keys:可能使用的索引
– key:实际使用的索引
– key_len:索引长度
– ref:引用的列
– rows:估计扫描的行数
– filtered:过滤后的行数百分比
– Extra:额外信息

2.1.2 执行计划分析步骤

# 执行计划分析步骤

## 1. 查看访问类型
– 优先选择访问类型为const、eq_ref、ref、range的执行计划
– 避免全表扫描(ALL)

## 2. 检查索引使用
– 确保使用了合适的索引
– 检查key列是否为NULL
– 验证索引是否被正确使用

## 3. 分析行估计
– 检查rows列的估计值是否合理
– 与实际行数比较,评估统计信息的准确性

## 4. 检查额外信息
– 避免Using temporary和Using filesort
– 优先使用Using index(覆盖索引)
– 注意Using where的使用情况

## 5. 分析连接类型
– 对于小表,Nested Loop Join可能更高效
– 对于大表,Hash Join可能更高效
– 对于有序数据,Merge Join可能更高效

2.2 SQL优化策略

2.2.1 索引优化

学习交流加群风哥QQ113257174
# 索引优化

## 1. 选择合适的索引
– 为频繁查询的列创建索引
– 为WHERE条件、ORDER BY和GROUP BY的列创建索引
– 为JOIN条件的列创建索引

## 2. 优化复合索引
– 遵循最左前缀原则
– 将最常用的列放在前面
– 将选择性高的列放在前面

## 3. 使用覆盖索引
– 包含查询所需的所有列
– 避免回表操作
– 减少IO操作

## 4. 避免索引失效
– 避免在索引列上使用函数
– 避免使用不等于(!=)操作符
– 避免使用IS NULL或IS NOT NULL
– 避免使用LIKE ‘%xxx’(前缀模糊匹配)

2.2.2 SQL语句优化

# SQL语句优化

## 1. 优化WHERE子句
– 将最选择性的条件放在前面
– 避免使用OR操作符,使用UNION代替
– 避免使用LIKE ‘%xxx’(前缀模糊匹配)
– 合理使用IN和EXISTS

## 2. 优化JOIN操作
– 确保连接列有索引
– 小表驱动大表
– 合理使用连接类型
– 避免笛卡尔积

## 3. 优化聚合操作
– 利用索引加速GROUP BY
– 合理使用HAVING和WHERE
– 避免在HAVING中使用复杂表达式

## 4. 优化子查询
– 合理使用子查询
– 避免嵌套过深的子查询
– 考虑使用JOIN代替子查询

## 5. 优化排序操作
– 利用索引的有序性
– 确保ORDER BY子句与索引顺序一致
– 避免使用不同方向的排序

2.3 性能考虑

# 性能考虑

## 1. 查询性能
– 减少数据扫描范围
– 利用索引加速查询
– 避免全表扫描
– 减少回表操作

## 2. 写入性能
– 批量写入数据
– 合理设置事务大小
– 控制索引数量
– 避免大事务

## 3. 存储开销
– 合理设计表结构
– 控制索引数量和大小
– 定期清理无用数据
– 合理设置分区策略

## 4. 系统资源
– 监控CPU使用率
– 监控内存使用率
– 监控IOPS
– 监控网络吞吐量

## 5. 维护成本
– 定期更新统计信息
– 定期重建索引
– 监控慢查询
– 定期优化SQL语句

生产环境建议:制定完善的SQL优化策略,定期分析执行计划,优化查询性能。学习交流加群风哥QQ113257174

Part03-生产环境项目实施方案

3.1 执行计划实施方案

3.1.1 执行计划分析工具

# 执行计划分析工具

## 1. EXPLAIN命令
– 基本使用:EXPLAIN SELECT …
– 详细分析:EXPLAIN ANALYZE SELECT …
– 查看执行计划:SHOW EXPLAIN FOR <query_id>

## 2. TiDB Dashboard
– 慢查询分析:查看慢查询的执行计划
– 执行计划可视化:图形化展示执行计划
– 性能分析:分析查询性能瓶颈

## 3. 第三方工具
– MySQL Workbench:可视化执行计划
– Navicat:执行计划分析
– DBeaver:执行计划分析

## 4. 自定义脚本
– 编写脚本分析执行计划
– 自动识别性能问题
– 生成优化建议

3.1.2 执行计划优化流程

# 执行计划优化流程

## 1. 收集慢查询
– 开启慢查询日志
– 设置合理的long_query_time
– 收集慢查询语句

## 2. 分析执行计划
– 使用EXPLAIN分析执行计划
– 识别性能瓶颈
– 确定优化方向

## 3. 优化SQL语句
– 调整WHERE条件
– 优化JOIN操作
– 调整ORDER BY和GROUP BY
– 优化子查询

## 4. 优化索引
– 创建合适的索引
– 调整复合索引的列顺序
– 使用覆盖索引
– 清理无用索引

## 5. 验证优化效果
– 测试查询性能
– 分析执行计划变化
– 确认优化效果

## 6. 监控与维护
– 监控优化后的查询性能
– 定期分析执行计划
– 及时调整优化策略

3.2 SQL优化实施方案

3.2.1 SQL优化步骤

# SQL优化步骤

## 1. 识别问题SQL
– 分析慢查询日志
– 监控查询性能
– 识别高频查询

## 2. 分析执行计划
– 使用EXPLAIN分析执行计划
– 识别性能瓶颈
– 确定优化方向

## 3. 优化SQL语句
– 调整WHERE条件
– 优化JOIN操作
– 调整ORDER BY和GROUP BY
– 优化子查询

## 4. 优化索引
– 创建合适的索引
– 调整复合索引的列顺序
– 使用覆盖索引
– 清理无用索引

## 5. 测试优化效果
– 测试查询性能
– 分析执行计划变化
– 确认优化效果

## 6. 应用优化方案
– 部署优化后的SQL语句
– 更新应用程序代码
– 监控优化效果

3.2.2 SQL优化工具

# SQL优化工具

## 1. TiDB内置工具
– TiDB Dashboard:慢查询分析
– EXPLAIN命令:执行计划分析
– ANALYZE TABLE:更新统计信息

## 2. 第三方工具
– pt-query-digest:分析慢查询日志
– MySQLTuner:MySQL配置和性能分析
– Percona Monitoring and Management:监控和分析

## 3. 自定义脚本
– 慢查询分析脚本
– 执行计划分析脚本
– 索引使用情况分析脚本

## 4. 监控工具
– Prometheus + Grafana:监控查询性能
– Nagios:监控系统状态
– Zabbix:监控系统状态

3.3 监控实施方案

3.3.1 监控指标设置

# 监控指标设置

## 1. 查询性能监控
– 慢查询数量:监控慢查询的数量
– 查询响应时间:监控查询的响应时间
– 扫描行数:监控查询扫描的数据行数
– 索引使用情况:监控索引的使用频率

## 2. 执行计划监控
– 全表扫描次数:监控全表扫描的次数
– 临时表使用次数:监控临时表的使用次数
– 文件排序次数:监控文件排序的次数
– 索引扫描次数:监控索引扫描的次数

## 3. 系统资源监控
– CPU使用率:监控CPU的使用情况
– 内存使用率:监控内存的使用情况
– IOPS:监控磁盘IO操作
– 网络吞吐量:监控网络传输速度

## 4. 告警设置
– 慢查询告警:当慢查询数量超过阈值时告警
– 全表扫描告警:当全表扫描次数超过阈值时告警
– 系统资源告警:当系统资源使用率超过阈值时告警

3.3.2 监控工具使用

# 监控工具使用

## 1. Prometheus + Grafana
– 部署Prometheus收集监控数据
– 配置Grafana仪表盘
– 设置告警规则

## 2. TiDB Dashboard
– 使用TiDB内置的Dashboard
– 监控集群状态
– 查看慢查询
– 分析性能问题

## 3. 自定义监控脚本
– 编写自定义监控脚本
– 定期检查执行计划
– 生成性能报告

## 4. 日志分析
– 分析慢查询日志
– 识别性能问题
– 排查故障

风哥提示:建立完善的监控体系,及时发现和解决SQL性能问题。更多学习教程公众号风哥教程itpux_com

Part04-生产案例与实战讲解

4.1 执行计划实战案例

# 执行计划实战案例

## 1. 案例背景
– 表:fgedu_orders(订单表)
– 数据量:1000万行
– 查询:SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;

## 2. 分析过程

### 步骤1:查看执行计划
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;

### 步骤2:分析执行计划输出
– id: 1
– select_type: SIMPLE
– table: fgedu_orders
– type: ALL
– possible_keys: NULL
– key: NULL
– key_len: NULL
– ref: NULL
– rows: 10000000
– filtered: 10.00
– Extra: Using where

### 步骤3:识别问题
– 访问类型为ALL(全表扫描)
– 未使用索引
– 估计扫描1000万行

### 步骤4:优化方案
– 创建复合索引:(user_id, status)

### 步骤5:实施优化
mysql> ALTER TABLE fgedu_orders ADD INDEX idx_user_id_status (user_id, status);

### 步骤6:验证优化效果
mysql> EXPLAIN SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;

### 步骤7:分析优化后的执行计划
– id: 1
– select_type: SIMPLE
– table: fgedu_orders
– type: ref
– possible_keys: idx_user_id_status
– key: idx_user_id_status
– key_len: 82
– ref: const,const
– rows: 100
– filtered: 100.00
– Extra: NULL

## 3. 优化效果
– 访问类型从ALL变为ref
– 使用了复合索引idx_user_id_status
– 估计扫描行数从1000万行减少到100行
– 查询性能显著提升

4.2 SQL优化实战案例

# SQL优化实战案例

## 1. 案例背景
– 表:fgedu_users(用户表)和fgedu_orders(订单表)
– 数据量:fgedu_users 100万行,fgedu_orders 1000万行
– 查询:SELECT u.name, o.order_no, o.amount FROM fgedu_users u JOIN fgedu_orders o ON u.id = o.user_id WHERE u.status = ‘active’ AND o.created_at > ‘2024-01-01’;

## 2. 分析过程

### 步骤1:查看执行计划
mysql> EXPLAIN SELECT u.name, o.order_no, o.amount FROM fgedu_users u JOIN fgedu_orders o ON u.id = o.user_id WHERE u.status = ‘active’ AND o.created_at > ‘2024-01-01’;

### 步骤2:分析执行计划输出
– id: 1
– select_type: SIMPLE
– table: u
– type: ALL
– possible_keys: PRIMARY
– key: NULL
– key_len: NULL
– ref: NULL
– rows: 1000000
– filtered: 10.00
– Extra: Using where

– id: 1
– select_type: SIMPLE
– table: o
– type: ref
– possible_keys: idx_user_id
– key: idx_user_id
– key_len: 4
– ref: fgedudb.u.id
– rows: 10
– filtered: 50.00
– Extra: Using where

### 步骤3:识别问题
– fgedu_users表使用全表扫描
– 未使用status索引
– 连接操作效率低

### 步骤4:优化方案
– 在fgedu_users表上创建status索引
– 在fgedu_orders表上创建(user_id, created_at)复合索引
– 调整查询语句,确保使用索引

### 步骤5:实施优化
mysql> ALTER TABLE fgedu_users ADD INDEX idx_status (status);
mysql> ALTER TABLE fgedu_orders ADD INDEX idx_user_id_created_at (user_id, created_at);

### 步骤6:验证优化效果
mysql> EXPLAIN SELECT u.name, o.order_no, o.amount FROM fgedu_users u JOIN fgedu_orders o ON u.id = o.user_id WHERE u.status = ‘active’ AND o.created_at > ‘2024-01-01’;

### 步骤7:分析优化后的执行计划
– id: 1
– select_type: SIMPLE
– table: u
– type: ref
– possible_keys: PRIMARY,idx_status
– key: idx_status
– key_len: 82
– ref: const
– rows: 100000
– filtered: 100.00
– Extra: NULL

– id: 1
– select_type: SIMPLE
– table: o
– type: ref
– possible_keys: idx_user_id,idx_user_id_created_at
– key: idx_user_id_created_at
– key_len: 12
– ref: fgedudb.u.id
– rows: 5
– filtered: 100.00
– Extra: Using where; Using index

## 3. 优化效果
– fgedu_users表使用ref访问类型,使用idx_status索引
– fgedu_orders表使用ref访问类型,使用idx_user_id_created_at索引
– 估计扫描行数显著减少
– 查询性能显著提升

4.3 性能分析与调优

# 性能分析与调优

## 1. 测试环境
– 数据库:TiDB 7.5.0
– 服务器:8核16GB
– 表:fgedu_orders(1000万行)

## 2. 测试场景
– 未优化的查询
– 优化后的查询

## 3. 性能测试

### 场景1:简单查询
– 未优化:SELECT * FROM fgedu_orders WHERE user_id = 1 AND status = ‘completed’;
– 响应时间:1.5秒
– 扫描行数:1000万行
– 执行计划:全表扫描

– 优化后:创建复合索引 (user_id, status)
– 响应时间:0.05秒
– 扫描行数:100行
– 执行计划:索引扫描

### 场景2:连接查询
– 未优化:SELECT u.name, o.order_no FROM fgedu_users u JOIN fgedu_orders o ON u.id = o.user_id WHERE u.status = ‘active’;
– 响应时间:2.0秒
– 扫描行数:1000万行
– 执行计划:全表扫描

– 优化后:创建索引 idx_status (status) 和 idx_user_id (user_id)
– 响应时间:0.1秒
– 扫描行数:10万行
– 执行计划:索引扫描

### 场景3:排序查询
– 未优化:SELECT * FROM fgedu_orders WHERE status = ‘completed’ ORDER BY created_at DESC;
– 响应时间:1.8秒
– 扫描行数:1000万行
– 执行计划:全表扫描 + 文件排序

– 优化后:创建复合索引 (status, created_at)
– 响应时间:0.15秒
– 扫描行数:100万行
– 执行计划:索引扫描 + 索引排序

## 4. 调优建议
– 为频繁查询的列创建索引
– 合理设计复合索引的列顺序
– 利用覆盖索引减少回表操作
– 优化SQL语句,确保使用索引
– 定期分析执行计划,及时调整优化策略

生产环境建议:定期分析执行计划,优化SQL语句和索引,提高查询性能。from tidb视频:www.itpux.com

Part05-风哥经验总结与分享

5.1 最佳实践

TiDB执行计划与SQL优化的最佳实践:

  • 执行计划分析最佳实践:
    • 定期分析执行计划
    • 关注访问类型和索引使用
    • 检查行估计和额外信息
    • 比较实际执行时间和估计时间
  • SQL优化最佳实践:
    • 为频繁查询的列创建索引
    • 合理设计复合索引
    • 使用覆盖索引减少回表操作
    • 优化WHERE条件,确保使用索引
    • 合理使用JOIN操作
  • 监控与维护最佳实践:
    • 开启慢查询日志
    • 定期分析慢查询
    • 监控系统资源使用情况
    • 定期更新统计信息
    • 定期重建索引
  • 性能优化最佳实践:
    • 平衡查询性能和写入性能
    • 根据业务需求调整优化策略
    • 优化系统参数
    • 合理配置硬件资源

5.2 性能优化技巧

# 性能优化技巧

## 1. 执行计划分析技巧
– 使用EXPLAIN ANALYZE获取详细执行计划
– 关注type列,优先选择const、eq_ref、ref、range
– 检查key列,确保使用了合适的索引
– 分析rows列,评估扫描行数是否合理
– 注意Extra列,避免Using temporary和Using filesort

## 2. SQL语句优化技巧
– 避免SELECT *,只选择需要的列
– 合理使用WHERE条件,确保使用索引
– 优化JOIN操作,小表驱动大表
– 利用索引的有序性,优化ORDER BY操作
– 合理使用子查询,避免嵌套过深

## 3. 索引优化技巧
– 为频繁查询的列创建索引
– 合理设计复合索引的列顺序
– 使用覆盖索引减少回表操作
– 避免在索引列上使用函数
– 定期清理无用索引

## 4. 系统优化技巧
– 调整TiDB、TiKV、PD参数
– 优化操作系统参数
– 配置合适的硬件资源
– 建立完善的监控体系

## 5. 维护优化技巧
– 定期更新统计信息
– 定期重建索引
– 监控慢查询
– 分析执行计划变化
– 及时调整优化策略

5.3 常见问题与解决

# 常见问题与解决

## 1. 执行计划问题

### 问题1:全表扫描
– 症状:执行计划显示type为ALL
– 原因:未创建合适的索引,或查询条件不符合索引使用条件
– 解决:创建合适的索引,优化查询条件

### 问题2:索引未被使用
– 症状:执行计划显示key为NULL
– 原因:查询条件未包含索引列,或在索引列上使用了函数
– 解决:优化查询条件,确保包含索引列,避免在索引列上使用函数

### 问题3:统计信息过期
– 症状:执行计划估计行数与实际行数差异较大
– 原因:统计信息未及时更新
– 解决:定期更新统计信息,执行ANALYZE TABLE

### 问题4:临时表和文件排序
– 症状:执行计划显示Using temporary和Using filesort
– 原因:ORDER BY或GROUP BY的列未创建索引
– 解决:创建合适的索引,优化排序操作

## 2. SQL语句问题

### 问题1:慢查询
– 症状:查询响应时间长
– 原因:未使用索引,或索引设计不合理
– 解决:优化查询语句,创建合适的索引

### 问题2:复杂查询
– 症状:查询逻辑复杂,执行时间长
– 原因:子查询嵌套过深,或JOIN操作过多
– 解决:简化查询逻辑,拆分复杂查询

### 问题3:大事务
– 症状:事务执行时间长,占用系统资源
– 原因:事务包含过多操作
– 解决:拆分大事务,合理设置事务大小

## 3. 系统问题

### 问题1:系统资源不足
– 症状:查询性能下降,系统响应慢
– 原因:CPU、内存、IO等资源不足
– 解决:升级硬件,优化系统参数

### 问题2:参数配置不当
– 症状:查询性能未达到最佳
– 原因:系统参数配置不合理
– 解决:调整TiDB、TiKV、PD参数

### 问题3:监控缺失
– 症状:无法及时发现性能问题
– 原因:未建立完善的监控体系
– 解决:部署监控工具,设置合理的告警阈值

风哥提示:SQL优化是一个持续的过程,需要定期分析执行计划,优化查询语句和索引,以获得最佳性能。

持续学习:关注TiDB的新特性和最佳实践,不断优化SQL语句和执行计划。

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

联系我们

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

微信号:itpux-com

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