一、调优总原则(最重要)
- 80% 性能问题来自慢 SQL + 索引缺失
- 调优顺序:SQL 语句 → 索引 → 表结构 → 配置参数 → 架构
- 不要盲目改配置,先监控、再定位、最后优化
二、SQL 语句优化(最见效)
1. 定位慢查询
开启慢查询日志,捕获执行慢的 SQL:
slow_query_log = 1
long_query_time = 1 # 超过1秒记录
slow_query_log_file = /var/log/mysql/slow.log
log_queries_not_using_indexes = 1 # 记录未使用索引的SQL
常用分析工具:
mysqldumpslowpt-query-digest(Percona 工具)
2. 必须会用:EXPLAIN 执行计划
通过 EXPLAIN 查看 SQL 是否走索引、扫描行数、是否全表扫描。
重点关注字段:
- type :最优到最差
system > const > eq_ref > ref > range > index > ALL- 出现
ALL= 全表扫描,必须优化
- 出现
- key:实际使用的索引,为 NULL 说明没走索引
- rows:扫描行数,越小越好
- Extra :出现
Using filesort / Using temporary必须优化
3. 常见 SQL 优化规则
-
禁止
SELECT *,只查需要的字段 -
避免在索引列上运算 / 函数
错误:WHERE DATE(create_time) = '2025-01-01' 正确:WHERE create_time >= '2025-01-01' AND create_time < '2025-01-02' -
避免
!= / <> / IS NULL / OR导致索引失效 -
模糊查询
%xxx无法使用索引 -
JOIN 关联字段必须建立索引,且类型一致
-
少用子查询,推荐用 JOIN 代替
-
分页深度优化
错误:SELECT * FROM t LIMIT 1000000,10 正确:SELECT * FROM t WHERE id>1000000 LIMIT 10
三、索引优化(核心)
1. 索引设计原则
- 最左前缀原则:联合索引 (a,b,c),查询必须包含 a 才能命中索引
- 区分度高的字段放前面
- 单张表索引不超过 5 个
- 联合索引不超过 3 个字段
- 频繁更新的字段不建索引
- 小表不建索引(全表扫描更快)
2. 必须建索引的场景
- WHERE 条件频繁使用的字段
- JOIN 关联字段
- ORDER BY / GROUP BY 字段
- 覆盖索引(查询字段全部在索引中,无需回表)
3. 索引失效场景(高频)
- 索引列使用函数、运算、类型转换
- 以
%开头的模糊查询 - OR 连接的条件有一个字段无索引
- 使用
NOT IN / != / <> / IS NOT NULL - 联合索引不满足最左前缀
4. 索引最佳实践
-- 建立联合索引(最左前缀)
CREATE INDEX idx_user_status_create ON user(status, create_time);
-- 覆盖索引(避免回表)
CREATE INDEX idx_order_user_no ON order(user_id) INCLUDE (order_no, amount);
四、表结构优化
1. 字段类型选择(越小越好)
- 能用
TINYINT不用INT - 能用
INT不用BIGINT - 时间用
DATETIME不用字符串 - 字符串长度固定用
CHAR,可变用VARCHAR - 禁止使用
TEXT/BLOB做查询条件
2. 设计规范
- 必须有主键(推荐自增 ID/BIGINT)
- 所有字段设置
NOT NULL,用默认值代替 NULL - 大字段拆分到副表
- 禁止频繁
ALTER TABLE
3. 分表分库(大数据量必备)
- 单表超过 1000 万 考虑分表
- 水平分表:按时间、用户 ID 哈希
- 垂直分表:冷热字段分离
五、MySQL 配置优化(my.cnf)
1. 内存配置(最关键)
根据服务器内存调整:
8G 内存推荐配置
[mysqld]
# 连接数
max_connections = 1000
back_log = 512
# 缓冲池(最重要!)
innodb_buffer_pool_size = 6G # 设为物理内存的 50%~70%
# 日志
innodb_log_file_size = 2G
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 1 # 安全模式
sync_binlog = 1
# 临时表
tmp_table_size = 256M
max_heap_table_size = 256M
# 排序&连接
sort_buffer_size = 2M
join_buffer_size = 2M
read_buffer_size = 2M
# 其他
innodb_file_per_table = 1
innodb_flush_method = O_DIRECT
2. 核心参数说明
- innodb_buffer_pool_size:InnoDB 缓存,越大性能越好
- max_connections:最大连接数
- innodb_flush_log_at_trx_commit:1 = 最安全,2 = 高性能
- innodb_file_per_table:每个表独立表空间,推荐开启
六、架构层面优化
1. 读写分离
- 主库写,从库读
- 工具:MyCat、Sharding-JDBC、MySQL Router
2. 缓存
- 热点数据放 Redis,避免频繁查库
- 页面缓存、接口缓存
3. 防止数据库雪崩
- 限流
- 熔断
- 降级
- 超时控制
七、操作系统层面优化
- 关闭 swap
- 文件系统用 ext4/xfs
- IO 调度:noop /deadline
- 打开文件数限制调高
- 关闭数据库所在磁盘的 atime
八、日常监控与维护
1. 必看状态
SHOW ENGINE INNODB STATUS;
SHOW PROCESSLIST;
SHOW VARIABLES LIKE '%buffer_pool%';
SHOW STATUS LIKE '%Threads%';
2. 定期维护
- 定期分析表
ANALYZE TABLE - 优化表
OPTIMIZE TABLE(碎片整理) - 定期删除冗余索引
- 慢查询持续监控