先说说那个让我熬出黑眼圈的索引问题。都知道B+树索引能加速查询,但为什么有时候加了索引反而更慢?有次我在用户表给username字段建了索引,查单个用户确实快了,但做用户分页查询时,offset超过10万后查询直接崩了。后来才搞明白,问题出在回表查询上。比如这条SQL:
看着简单对吧?但用explain分析发现居然扫描了十几万行。解决办法其实挺巧妙的,用延迟关联优化:
子查询先用覆盖索引快速定位主键,再回表取数据,性能直接提升十倍。这种优化思路在很多大厂规范里都是必选项。
再说个实战中遇到的坑。有次上线新功能,日志里突然出现大量死锁错误。排查发现是两个事务在同时更新用户账户表:
事务A:
事务B:
这两个事务更新顺序相反,在并发时就会产生死锁。最后我们制定了开发规范:所有涉及多行更新的事务,必须按主键升序排序执行。这种细节在业务开发时特别容易忽略。
最近还在研究MySQL 8.0的窗口函数,这玩意儿真是分析神器。比如要计算每个用户的消费排名:
比原来用子查询的方式快了不止一个量级。不过要注意,窗口函数在大数据量时很吃内存,需要合理设置buffer大小。
说到优化,不得不提查询缓存这个坑货。看上去很美,但在高并发写入场景下,缓存频繁失效反而成了性能杀手。我们在压测时发现,关闭查询缓存后QPS反而提升了30%。现在很多互联网公司都直接禁用这功能,还不如用Redis做缓存。
还有一次让我记忆犹新的调优经历。有个报表查询要关联8张表,执行时间超过30秒。后来通过创建联合索引,把需要的列都覆盖进去,避免回表操作,最终优化到0.5秒。这里有个小技巧:
其实MySQL优化就是个不断踩坑的过程。最近我们在生产环境启用了SQL审计功能,把执行时间超过1秒的查询都记下来,每周组织开发一起review,慢慢培养大家的性能意识。效果很明显,现在团队新人写SQL都会主动explain一下。
数据库这玩意儿真是越挖越深,从简单的CRUD到架构设计,每个阶段都有新的挑战。下次准备和大家聊聊我们是怎么做分库分表的,那又是另一个血泪史了。不过话说回来,能把一个千万级数据库优化得服服帖帖,这种成就感确实很让人上瘾。
1126

被折叠的 条评论
为什么被折叠?



