GoldenDB慢SQL优化指南
GoldenDB慢SQL优化指南
也可通过# EXPLAIN 完全指南 结合一起阅读
1. 引言
GoldenDB是一款分布式数据库,在处理大规模数据时,慢SQL可能会导致系统性能下降、响应时间变长,甚至影响业务正常运行。本指南旨在帮助您理解慢SQL的原因、如何分析慢SQL,以及如何进行优化,使您能够更轻松地应对慢SQL问题。
2. 慢SQL的定义与识别
2.1 什么是慢SQL
慢SQL是指执行时间超过设定阈值的SQL语句。在GoldenDB中,通常认为执行时间超过1秒的SQL语句为慢SQL。
2.2 如何识别慢SQL
-
查看慢查询日志:
- CN节点慢日志:记录了SQL的执行总时间、执行计划时间等信息
- DN节点慢日志:记录了具体的SQL语句、执行时间、扫描行数等信息
-
监控告警:
- OMM页面的"执行线程阻塞"告警
- 慢SQL数量增加的告警
-
关键指标监控:
PlanTreeExecTime:执行计划树耗时DB connection_idduration:DB执行时间Rows_examined:扫描行数
3. 慢SQL的常见原因
3.1 未使用索引
- 现象:SQL执行时进行全表扫描,
Rows_examined值极大 - 原因:WHERE条件中的列没有创建索引
- 影响:需要扫描大量数据,执行时间长
3.2 SQL写法不当
- 现象:返回大结果集,执行时间长
- 原因:
- 使用
SELECT *查询所有列 - 查询范围过大,没有限制返回行数
- 条件选择性差,过滤效果不好
- 复杂的JOIN操作,没有合适的索引
- 子查询嵌套过深
- 使用
3.3 统计信息过时
- 现象:执行计划不合理
- 原因:表的统计信息过时,优化器选择了错误的执行计划
- 影响:即使有索引,也可能选择全表扫描
3.4 锁等待
- 现象:SQL执行时间主要消耗在锁等待上
- 原因:并发更新同一记录导致锁竞争
- 影响:SQL执行被阻塞,响应时间变长
3.5 分布式环境特有的问题
- 现象:跨分片查询,执行时间长
- 原因:
- 数据分布不均匀
- 跨分片JOIN操作
- 大量数据在网络传输
- 影响:网络开销大,执行时间长
4. 慢日志分析方法
4.1 CN慢日志分析
CN慢日志包含两部分:
- 整体执行情况:记录了SQL的总执行时间、各阶段耗时等
- 子语句执行情况:记录了执行计划中子语句的执行情况
关键字段分析
字段
说明
分析要点
TotalExecTime
语句执行的总时间
了解整体执行耗时
PlanTreeExecTime
执行计划树的总时间
占总时间的比例,判断是否为执行计划问题
DB connection_id duration
DB侧执行时间
如果该值较大,说明问题出在DB侧
sqltoRoute
语句从执行线程下发到路由线程的耗时
超过100us说明路由线程积压
TaskWait
语句加入到执行队列中到真正开始执行的等待时间
时间长说明队列积压
workerdelay
listener将task放入队列,到worker开始执行的时间
时间长说明有其他语句占用了worker线程
worker
空闲worker线程被唤醒后处理task的时间
时间长且num大说明结果集大
restoExec
路由线程或worker线程将结果处理后给执行线程发消息的时间
时间长说明执行线程消息积压
4.2 DN慢日志分析
DN慢日志记录了SQL在数据节点的执行情况:
字段
说明
分析要点
Query_time
查询执行时间
了解DB侧执行耗时
Lock_time
锁等待时间
时间长说明存在锁竞争
Rows_sent
返回行数
与Rows_examined对比,判断查询效率
Rows_examined
扫描行数
数值过大说明可能未使用索引
4.3 执行计划分析
使用EXPLAIN命令分析SQL的执行计划:
EXPLAIN SELECT * FROM order_info WHERE order_status = 2 AND create_time > '2026-04-01';
关键关注:
type:查询类型,ALL表示全表扫描,range表示范围查询,ref表示索引查找possible_keys:可能使用的索引key:实际使用的索引rows:估计需要扫描的行数filtered:过滤后的行数占比Extra:额外信息,如Using index、Using where等
4.4 检查表结构与索引
使用SHOW CREATE TABLE命令查看表结构和索引:
SHOW CREATE TABLE order_info\G
检查WHERE条件中的列是否有相应的索引,以及索引的设计是否合理。
5. 优化策略
5.1 索引优化
- 创建合适的索引:根据SQL的WHERE条件创建索引
- 复合索引:对于多个条件的查询,创建复合索引
- 索引顺序:将选择性高的列放在索引前面
- 覆盖索引:创建包含查询所需列的索引,减少回表操作
- 删除冗余索引:定期清理不必要的索引,减少维护成本
示例:
-- 创建复合索引
CREATE INDEX idx_order_status_create_time ON order_info(order_status, create_time);
-- 创建覆盖索引
CREATE INDEX idx_user_id_amount ON order_info(user_id, amount);
5.2 SQL写法优化
问题
优化前
优化后
使用SELECT *
SELECT * FROM order_info WHERE ...
SELECT id, order_no, amount FROM order_info WHERE ...
查询范围过大
WHERE create_time > '2026-04-01'
WHERE create_time > '2026-04-15' LIMIT 1000
条件选择性差
WHERE order_status = 2
WHERE order_status = 2 AND user_id = xxx
复杂子查询
SELECT * FROM (SELECT * FROM order_info WHERE ...) t WHERE ...
SELECT * FROM order_info WHERE ... AND ...
隐式类型转换
WHERE id = '123'
WHERE id = 123
函数操作索引列
WHERE DATE(create_time) = '2026-04-15'
WHERE create_time BETWEEN '2026-04-15 00:00:00' AND '2026-04-15 23:59:59'
5.3 统计信息更新
定期更新表的统计信息,帮助优化器选择更好的执行计划:
-- 更新表统计信息
ANALYZE TABLE order_info;
-- 优化表
OPTIMIZE TABLE order_info;
5.4 分布式环境优化
- 合理分片:根据业务特点选择合适的分片键,确保数据分布均匀
- 避免跨分片查询:尽量在单个分片内完成查询操作
- 批量操作:将多个小查询合并为批量操作,减少网络开销
- 使用绑定变量:减少SQL解析开销,提高执行效率
5.5 紧急处理措施
当遇到慢SQL导致系统性能下降时:
-
定位阻塞SQL:
grep "exec sql too long" dbproxy* -
Kill阻塞链路:
kill connection $dialogid; -
临时优化SQL:限制返回行数
SELECT * FROM order_info WHERE order_status = 2 AND create_time > '2026-04-01' LIMIT 1000;
6. 最佳实践
6.1 开发规范
-
索引规范:
- 根据SQL编写需求创建合适索引
- 避免创建过多索引,影响写入性能
- 定期检查索引使用情况
-
SQL编写规范:
- 避免使用
SELECT * - 使用分页查询限制返回行数
- WHERE条件列要有索引
- 避免在索引列上进行函数操作
- 使用绑定变量,减少SQL解析开销
- 避免使用
-
评审流程:
- DDL变更前进行SQL性能评审
- 新功能上线前进行性能测试
- 定期Review慢SQL列表
6.2 日常维护
- 定期分析:定期分析慢查询日志,优化慢SQL
- 索引维护:定期检查索引使用情况,删除冗余索引
- 统计信息:定期执行
ANALYZE TABLE更新统计信息 - 表结构优化:根据业务发展调整表结构和索引
6.3 监控与告警
- 慢SQL监控:监控
EXEC** process run too long日志出现频率 - 执行时间监控:监控
PlanTreeExecTime和DB connection_idduration - 全表扫描监控:监控
Rows_examined过大的SQL - 锁等待监控:监控锁等待时间过长的SQL
- 分布式查询监控:监控跨分片查询的执行情况
7. 案例分析
7.1 案例背景
现象:
- 执行线程阻塞告警触发
- 业务查询响应时间从毫秒级飙升至数十秒
- DN节点CPU使用率飙升至80%+
分析:
- 查看慢日志发现SQL:
select * from order_info where order_status = 2 and create_time > '2026-04-01' - 执行计划显示全表扫描,
Rows_examined: 5823671 - 检查表结构发现
order_status和create_time列无索引 - CN慢日志显示
DB connection_id duration: 38450000us,说明问题出在DB侧
解决方案:
- 创建复合索引:
CREATE INDEX idx_order_status_create_time ON order_info(order_status, create_time); - 优化SQL写法,避免使用
SELECT *:SELECT id, order_no, amount FROM order_info WHERE order_status = 2 AND create_time > '2026-04-01' - 限制返回行数:
SELECT id, order_no, amount FROM order_info WHERE order_status = 2 AND create_time > '2026-04-01' LIMIT 1000
效果:
- 执行计划变为范围查询,仅扫描15万行
- SQL执行时间从38秒降至毫秒级
- 系统性能恢复正常
7.2 案例分析:跨分片查询优化
现象:
- 跨分片JOIN查询执行时间长
- 网络传输数据量大
分析:
- SQL:
SELECT o.id, o.order_no, u.username FROM order_info o JOIN user_info u ON o.user_id = u.id WHERE o.create_time > '2026-04-01' - 订单表和用户表分别在不同分片
- 执行计划显示需要在所有分片上执行查询,然后在CN节点进行JOIN
解决方案:
- 调整分片策略,将相关表放在同一分片
- 或者创建本地索引,减少跨分片数据传输
- 优化SQL,减少返回数据量:
SELECT o.id, o.order_no, u.username FROM order_info o JOIN user_info u ON o.user_id = u.id WHERE o.create_time > '2026-04-01' LIMIT 100
效果:
- 执行时间从10秒降至1秒以内
- 网络传输数据量减少90%
8. 总结
慢SQL优化是GoldenDB性能管理的重要组成部分。通过合理的索引设计、SQL写法优化、定期维护和监控,可以有效避免和解决慢SQL问题,提高系统性能和稳定性。
记住以下关键点:
- WHERE条件列必须创建索引,避免全表扫描
- 避免使用
SELECT *和过大的查询范围 - 定期更新统计信息,确保优化器选择正确的执行计划
- 注意分布式环境的特殊性,合理设计分片策略
- 建立完善的监控和告警机制,及时发现和处理慢SQL
- 制定开发规范,从源头避免慢SQL
- 感谢你赐予我前进的力量

