数据库调优这个话题,做开发的应该都踩过坑。我见过太多人,写 SQL 时只顾功能实现,等到线上崩了才慌慌张张找问题。其实,调优没那么玄乎,核心就五件事:索引、SQL 写法、表结构、缓存、硬件配置。今天聊聊这些,不说废话,全是实战经验。

先说索引,这是最基础也是最容易见效的。很多人以为给所有字段加索引就完事了,那叫浪费资源。索引不是越多越好,每多一个索引,写入数据时就要多维护一棵 B+ 树。真正该加索引的,是 WHERE 条件里的字段、ORDER BY 和 JOIN 的关联键。比如你查用户表,经常按手机号查,那给手机号字段建个唯一索引,查询速度能从秒级降到毫秒级。但如果给状态字段加索引,基本没用——状态字段的取值很少,MySQL 优化器会认为全表扫描更划算。还有,复合索引要遵循最左前缀原则,索引 (a,b,c) 能覆盖 a、a+b+c 三种查询,但跳过 a 直接查 b、c,索引就失效了。
第二点是 SQL 写法,这活儿不少人干得糙。我见过最经典的错误,是在 WHERE 条件里对索引字段做函数运算。比如写 ,会让索引失效,因为数据库要先把每一行的 time 转成日期再比较。正确写法是 。另外,避免使用 ,只取需要的字段能减少数据传输量。分页查询也别用 这种写法,数据库要扫描 10 万行才能返回 10 行,改成基于主键的游标分页,性能和稳定性都强太多。优化 SQL 时,记得用 EXPLAIN 看执行计划,关注 type 字段——从 system 到 all,性能依次下降。
表结构设计是调优的根基,但往往被忽视。比如字段类型选择,能选 INT 就别用 VARCHAR,能选 SMALLINT 就别用 BIGINT。我见过有人把用户 ID 设为 VARCHAR(255),查询一次就要进行类型转换,慢几毫秒。数据量大了,这种浪费会成倍放大。尽量加 NOT NULL 约束,因为 NULL 在索引里处理更复杂,查询时还得额外判断。分表分库是常见策略,但别一上来就搞。先看看你的数据量,单表超过 500 万行确实要考虑分表,但分表方案要提前规划——按什么分、跨表查询怎么处理、数据迁移怎么做。别等业务跑不动了才临时抱佛脚。
缓存策略是提升性能的大杀器,但很多人用不好。Redis 用得对,能把数据库查询次数降到原来的十分之一。但缓存不是银弹,热点数据失效时,大量请求同时穿透到数据库,瞬间就能把数据库打垮,这叫缓存雪崩。解决办法很简单:给缓存设置随机过期时间,别让它们同时失效。还有缓存穿透,查询一个不存在的 key,每次请求都打到数据库。可以用布隆过滤器拦截,或者把空结果也缓存起来,但缓存时间要短。缓存更新策略也得想清楚,是先更新数据库还是先删缓存?常见做法是先更新数据库,再删缓存,这样能避免并发更新时数据不一致的问题。
硬件和配置这块,很多人觉得不就是加内存换 SSD 吗,但事情没那么简单。MySQL 的 参数直接决定了数据在内存中的缓存能力。如果服务器内存是 64 GB,建议把这个值设到 40‑50 GB,剩下的留给操作系统和其他进程。但别设太大,否则会导致内存溢出。日志文件大小也要注意, 设得太小会导致频繁的日志切换,影响写入性能。我见过一个场景,日志文件只有 256 MB,写入量大时每秒要切换好几次日志,性能直接腰斩。把日志文件调到 1 GB 以上,写入性能立竿见影。连接数也要控制, 别设太高,否则并发连接过多,MySQL 只忙着处理连接就吃不消了。
说说调优的节奏和顺序。别一上来就调硬件配置,那是治标不治本。正确的顺序是:先看慢查询日志,找到真正的瓶颈;然后优化 SQL 把慢查询干掉;接着检查索引是否合理,是否有冗余或缺失;再考虑表结构能否优化,字段类型、分表策略是否需要调整;最后再考虑缓存和配置。这个过程要反复迭代,因为业务在变,数据量在涨,调优不是一次性工作。我见过一个团队,调完一次就以为万事大吉,结果半年后业务量翻倍,同样的 SQL 又变慢了。所以,定期做性能巡检,关注慢查询的增长趋势,才能让数据库一直保持好状态。
总结一下,数据库调优不是玄学,也不是高深的技术。核心就是这五个方向:索引、SQL、表结构、缓存、配置。每个方向都有具体可操作的方法,没有捷径,但只要按顺序一步步做,查询性能提升十倍真的不是梦。记住,调优是为了让数据库更好地服务业务,而不是炫技。把每一步都做到位,你的数据库就能跑得快、跑得稳。


