MySQL性能优化实战:慢查询到毫秒响应全链路突破
|
MySQL性能优化实战:慢查询到毫秒响应全链路突破——这标题不是喊口号,是我2026年6月在某城商行核心账务系统里真刀真枪干出来的。当时单笔跨日终批量查余额的SQL平均耗时4.7秒,P99卡在6.2秒,DBA同事连监控告警阈值都设成5秒了——结果上线首周就触发137次告警。
文章配图,仅供参考 我们定位到罪魁祸首是t_transaction_detail表上的一个LEFT JOIN子句,它关联了t_customer_info但没走索引;explain显示type=ALL,rows=842万——可表明明有customer_id索引啊?后来翻binlog才发现,MySQL 8.0.33有个隐藏坑:当字段声明为VARCHAR(255) COLLATE utf8mb4_0900_as_cs,而JOIN条件里写的是CONVERT(cust_id USING utf8mb4),字符集转换直接让索引失效。这个细节连Percona官方博客2025年12月的patch note都没提,我是在抓取optimizer trace时发现"range_analysis_alternatives"里反复跳过该索引的。(对,就是那个“优化器认为走全表更快”的诡异判断)改完collation对齐,查询降到890ms;再加覆盖索引(customer_id, balance, trans_time),落到210ms;最后用Query Rewrite插件把原SQL中"SELECT "强制改写成显式字段列表,P99压到63ms。中间还翻过车:加完索引第二天凌晨2:17突然雪崩——原来是运维同事在备份窗口执行了ANALYZE TABLE,更新统计信息后优化器重新选错了执行计划,回退到嵌套循环+临时表。后来我们锁定了histogram级别为200,并禁用了自动ANALYZE——这招现在还被他们DBA写进SOP第4.2条。 MySQL性能优化实战:慢查询到毫秒响应全链路突破。 2026年6月那次压测,我把t_transaction_detail按trans_date做了LIST分区,但发现分区裁剪失败——因为WHERE里写的是DATE(trans_time),而trans_time是DATETIME类型。MySQL没做隐式下推,反而把函数丢到每一分区里算。换成trans_time >= '2026-06-01' AND trans_time < '2026-06-02'后,分区剪枝才生效。这里有个反常识点:即便开了optimizer_switch='condition_fanout_filter=on',函数包裹的字段仍无法触发剪枝。我试过hint /+ USE_INDEX(t_transaction_detail idx_dt) /都没用——它根本不在索引树里找。 客户现场那台Dell R750物理机,内存384G,磁盘是PM1735a NVMe(注意不是U.2形态,是AIC插卡式),但I/O wait一度飙到27%。用iostat -xmt 1看,r_await常驻18ms,w_await压在0.3ms——说明读瓶颈在CPU解压环节,不是存储。原来应用层启用了my.cnf里[mysqld]段落的innodb_page_compression=ZSTD,而ZSTD压缩页在buffer pool里解压要占CPU。关掉压缩、换回NONE,QPS从11200涨到14600,延迟曲线方差缩窄40%。这事挺讽刺:新技术堆得越多,越容易踩空——ZSTD是MySQL 8.0.29新增的,默认打开,可没人告诉你,高频小事务场景下它比LZ4还吃CPU。 新技术真香。 目前还在赌一把:准备把t_transaction_detail的历史分区迁到HeatWave Serverless集群做只读卸载,但AWS团队说他们的MySQL兼容层不支持FULLTEXT on JSON列——而我们的模糊检索刚好靠这个。所以……下周得去杭州阿里云总部,带测试数据现场拉通RDS for MySQL与PolarDB-X 2.0的Join能力,看能不能混布。要是不行,就只能砍需求了。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


MySQL高可用架构:5年实战从单点到自动容灾
MySQL事务控制无障碍设计指南
VR开发编译技巧与性能优化实战指南