您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# MySQL的慢SQL怎么优化
## 前言
在数据库运维和开发过程中,慢SQL是影响系统性能的常见问题。当SQL查询执行时间超过预期阈值时,不仅会导致用户体验下降,还可能引发数据库连接池耗尽、服务器资源过载等连锁反应。本文将系统性地介绍MySQL慢SQL的优化方法,涵盖监控识别、分析诊断、优化方案和预防措施等方面内容。
## 一、什么是慢SQL
### 1.1 定义
慢SQL是指执行时间超过预设阈值的SQL语句。在MySQL中,默认的慢查询阈值是10秒(可通过`long_query_time`参数调整)。
### 1.2 影响
- 系统资源消耗增加
- 并发处理能力下降
- 用户体验恶化
- 可能引发雪崩效应
## 二、如何发现慢SQL
### 2.1 慢查询日志
```sql
-- 开启慢查询日志
SET GLOBAL slow_query_log = 'ON';
-- 设置慢查询阈值(秒)
SET GLOBAL long_query_time = 2;
-- 记录未使用索引的查询
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 查看当前运行的慢查询
SELECT * FROM information_schema.PROCESSLIST
WHERE TIME > 10 AND COMMAND != 'Sleep';
-- 查询performance_schema中的语句统计
SELECT * FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WT DESC LIMIT 10;
EXPLN FORMAT=JSON SELECT * FROM orders WHERE user_id = 100;
关键指标解读: - type:从优到差依次为 system > const > eq_ref > ref > range > index > ALL - key:实际使用的索引 - rows:预估扫描行数 - Extra:重要补充信息(Using filesort, Using temporary等)
-- 开启会话级性能分析
SET profiling = 1;
-- 执行待分析的SQL
SELECT * FROM large_table WHERE condition;
-- 查看分析结果
SHOW PROFILE;
-- 查看详细IO和CPU消耗
SHOW PROFILE BLOCK IO, CPU FOR QUERY 1;
-- 1. 隐式类型转换
SELECT * FROM users WHERE phone = 13800138000; -- phone是varchar类型
-- 2. 函数操作索引列
SELECT * FROM orders WHERE DATE(create_time) = '2023-01-01';
-- 3. 前导模糊查询
SELECT * FROM products WHERE name LIKE '%手机%';
-- 4. 不满足最左前缀
ALTER TABLE users ADD INDEX idx_composite(name, age);
SELECT * FROM users WHERE age > 20; -- 无法使用索引
-- 优化前(全表扫描)
SELECT * FROM orders WHERE status = 'completed' AND create_time > '2023-01-01';
-- 优化后(添加复合索引)
ALTER TABLE orders ADD INDEX idx_status_time(status, create_time);
-- 原查询(嵌套子查询)
SELECT * FROM users WHERE id IN (
SELECT user_id FROM orders WHERE amount > 1000
);
-- 优化为JOIN
SELECT u.* FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 1000;
-- 低效写法
SELECT * FROM large_table LIMIT 1000000, 10;
-- 优化方案1:使用主键分页
SELECT * FROM large_table WHERE id > 1000000 LIMIT 10;
-- 优化方案2:延迟关联
SELECT t.* FROM large_table t
JOIN (SELECT id FROM large_table LIMIT 1000000, 10) tmp ON t.id = tmp.id;
-- 低效做法(应用程序循环)
for id in ids:
DELETE FROM table WHERE id = id
-- 高效批量操作
DELETE FROM table WHERE id IN (1,2,3,...);
[mysqld]
# 缓冲池大小(建议物理内存的50-75%)
innodb_buffer_pool_size = 12G
# 日志文件大小
innodb_log_file_size = 2G
# 连接数设置
max_connections = 500
thread_cache_size = 50
# 排序缓冲区
sort_buffer_size = 4M
join_buffer_size = 4M
-- 合理设置隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 控制事务大小
START TRANSACTION;
-- 批量插入10万条数据
INSERT INTO ... VALUES (...), (...), ...;
COMMIT;
-- 创建汇总表
CREATE TABLE sales_summary (
product_id INT PRIMARY KEY,
total_sales DECIMAL(12,2),
last_updated TIMESTAMP
);
-- 定期刷新
REPLACE INTO sales_summary
SELECT product_id, SUM(amount), NOW()
FROM orders
GROUP BY product_id;
-- 8.0+版本支持
SELECT /*+ PARALLEL(4) */ * FROM large_table WHERE condition;
-- 使用列式存储处理分析型查询
ALTER TABLE analytics_data ENGINE=ColumnStore;
-- 创建监控表
CREATE TABLE slow_query_monitor (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
query_digest VARCHAR(32),
sample_query TEXT,
exec_count INT,
avg_latency DECIMAL(10,3),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 定期从performance_schema采集数据
INSERT INTO slow_query_monitor(query_digest, sample_query, exec_count, avg_latency)
SELECT DIGEST_TEXT, DIGEST, COUNT_STAR, AVG_TIMER_WT/1000000000
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WT DESC LIMIT 10;
工具名称 | 用途 | 官网 |
---|---|---|
pt-query-digest | 慢日志分析 | percona.com |
sysbench | 压力测试 | github.com/akopytov/sysbench |
gh-ost | 在线DDL工具 | github.com/github/gh-ost |
Atlas | SQL中间件 | github.com/Qihoo360/Atlas |
注:本文基于MySQL 8.0版本编写,部分特性在早期版本可能不适用。实际生产环境优化时,请务必先在测试环境验证。 “`
(全文约6550字,实际字数可能因排版有所差异)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。