MySQL 数据库优化是面试高频大题,核心思路不是只改 SQL,而是分多层优化,从表结构设计、索引、SQL 语句、配置参数、架构、缓存、硬件这几个层面一起调整,目标就是降低查询耗时,减少锁冲突,提升并发能力,避免慢查询拖垮数据库。很多新手优化只会加索引,但是表设计不合理、SQL 写法错误、参数配置不当,就算加再多索引效果也很差,优化一定要先定位瓶颈,不要盲目优化,定位瓶颈最常用工具就是慢查询日志 explain 执行计划。
第一层 表结构设计优化
1 字段类型合理选择,能用 tinyint 就不要用 int,能用 varchar 固定长度就不要随便用 text,尽量避免大字段
2 大字段拆分,text blob 这类大字段单独拆到扩展表,主表只存 id,减少主表行体积,提升缓存命中率
3 适度反范式,多表联查特别频繁的业务,可以冗余部分字段,减少 join 次数,但是要注意数据一致性维护
4 主键推荐自增主键,顺序写入,减少页分裂,不要频繁使用随机 uuid 做主键
5 表不要无限增长,大表做分表,历史数据归档
第二层 索引优化(重点)
1 建立合适索引,优先给 where、order by、group by、join 关联字段建索引
2 遵守最左前缀原则,联合索引从最左边字段开始匹配
3 避免索引失效场景,比如对索引字段使用函数、运算、like 左模糊 % xxx、隐式类型转换、or 条件、not in,这些都会让索引失效
4 控制索引数量,一张表索引不能太多,索引会降低 insert update delete 写入性能,还会占用磁盘
5 删除无效索引、重复索引,使用工具检查冗余索引
6 区分普通索引、唯一索引、联合索引,根据业务选择
第三层 SQL 语句优化
1 禁止 select ,只查询需要的字段,减少网络传输和内存消耗
2 大分页优化,limit 100000,10 这种深分页很慢,可以用子查询或者游标方式优化
3 join 优化,关联表小表驱动大表,关联字段必须有索引,减少嵌套循环扫描行数
4 group by order by 尽量利用索引,避免 filesort 临时排序
5 批量操作,批量 insert,不要循环单条插入,减少事务和网络开销
6 减少大事务,长事务会导致锁持有时间久,undo 日志膨胀,并发下降
第四层 MySQL 配置参数优化 InnoDB 为主
1 innodb_buffer_pool_size 最重要参数,一般设置为物理内存 50% 到 70%,把热点数据放在内存,减少磁盘 IO
2 innodb_log_file_size redo 日志大小,根据业务读写量调整
3 innodb_flush_log_at_trx_commit,根据业务对数据安全和性能取舍
4 连接数 max_connections,根据业务并发调整,不能无限调大
5 开启慢查询日志,设置 long_query_time,定期抓取慢 SQL 分析
6 调整临时表、排序缓冲区 sort_buffer_size 这类参数
第五层 架构与业务层优化
1 读写分离,主库写,从库读,分担查询压力
2 分库分表,水平分表垂直分库,单表数据量过大的时候使用
3 增加缓存,Redis 缓存热点查询结果,减少直接访问 MySQL,这是非常有效的优化手段
4 定时清理碎片,表大量 delete update 之后会产生碎片,定期 optimize table 整理表空间
5 主从复制,备份容灾,同时承担读请求
第六层 硬件与系统层面优化
1 使用 SSD 固态硬盘,相比机械磁盘 IO 性能提升巨大,对 InnoDB 随机读写帮助明显
2 提升内存,buffer_pool 依赖内存,内存越大缓存命中越高
3 操作系统层面调整文件句柄数,关闭不必要系统服务
优化标准流程
第一步 开启慢查询日志,收集慢 SQL
第二步 explain 分析执行计划,查看 type、rows、Extra,判断有没有全表扫描、filesort
第三步 判断是索引问题还是 SQL 写法问题,或者表结构设计问题
第四步 修改之后压测验证,对比优化前后耗时
第五步 持续监控,不是优化一次就永久生效,业务增长瓶颈会变化
容易踩坑点清单
1 盲目加索引,写入性能暴跌
2 只优化查询,忽略长事务锁冲突
3 大表没有归档,单表千万行之后性能断崖下降
4 select 长期使用,没有改成指定字段
5 深分页 limit 没有优化,页面越往后越卡
【常见问题】
问题 1 mysql 优化第一步应该做什么
回答 1 mysql 优化第一步是定位瓶颈,开启慢查询日志,使用 explain 分析执行计划,不要盲目加索引。
问题 2 explain 里面 type 出现 all 是什么意思
回答 1 explain type=all 代表全表扫描,是 mysql 性能很差的表现,优先检查索引是否缺失或者索引失效。
问题 3 innodb_buffer_pool_size 作用是什么
回答 3 innodb_buffer_pool_size 是 mysql 最重要内存参数,缓存热点数据索引,减少磁盘 IO,是 mysql 配置优化核心项。
问题 4 分库分表是不是 mysql 优化首选方案
回答 3 不是,分库分表属于大业务后期方案,优先完成 SQL、索引、表结构、缓存优化,单表数据量实在过大再考虑分库分表。
【免责申明】
本内容为 MySQL 通用优化思路,不同业务 OLTP OLAP 场景优化侧重点不一样,参数调整需要结合服务器内存 CPU 压测验证,生产环境修改参数前务必做好备份。


