
从一个慢查询到全链路重构这一周值不值我觉得值。事情要从一个普通的周三说起。产品经理在群里了我运营反馈说后台订单导出一直在转圈三分钟了还没出来客户在催。我打开监控面板看到那个接口的响应时间——平均12.8秒P99已经超过了30秒。关键是这接口每天被调用上千次。排查过程并不复杂。打开慢查询日志一条SQL映入眼帘sql复制下载SELECT o., u.name, u.phone, p.product_name, p.sku FROM orders o LEFT JOIN users u ON o.user_id u.id LEFT JOIN products p ON o.product_id p.id WHERE o.create_time BETWEEN 2025-01-01 AND 2025-01-31 ORDER BY o.create_time DESC LIMIT 10000 OFFSET 0;十万订单量三张表关联没有覆盖索引还要排序——MySQL看了都沉默。当时的第一反应是加索引、调参数。但当我仔细看了一遍整个数据访问层的代码后我发现问题远不止一条SQL那么简单Entity里堆满了ManyToOne和OneToManyJPA的N1查询遍地都是分页用的是内存分页先把所有数据查出来再截取批量操作是一条条循环insert的。这不是修一个接口的问题是整个底层数据访问层出了系统性故障。一、放弃优雅选择可控原来的代码用的是Spring Data JPA写起来确实爽——几行注解就能搞定关联查询。但代价是你根本不知道Hibernate替你生成了什么样的SQL。我决定换成MyBatis Plus。不是因为JPA不好而是在这个场景下我需要完全掌控每一条SQL。MyBatis Plus的LambdaQueryWrapper写起来也不比JPA复杂多少但SQL是白纸黑字写在Mapper里的执行计划一看便知。java复制下载// 之前JPA自动生成你猜它怎么查的 PageOrder findByCreateTimeBetween(LocalDateTime start, LocalDateTime end, Pageable pageable); // 之后SQL完全在手explain看得明明白白 Select(SELECT o., u.name, u.phone, p.product_name FROM orders o LEFT JOIN users u ON o.user_id u.id LEFT JOIN products p ON o.product_id p.id WHERE o.create_time BETWEEN #{start} AND #{end} ORDER BY o.create_time DESC) PageOrderVO queryOrderPage(PageOrderVO page, Param(start) LocalDateTime start, Param(end) LocalDateTime end);二、分页不是查出来再截取原来代码里一个很隐蔽的问题PageHelper在数据量大的时候会先查全部数据再内存分页。十万条数据全查出来内存不炸才怪。重写后分页逻辑下推到数据库层面。配合覆盖索引(create_time, id)分页查询的扫描行数从十万降到了几十条。三、批量操作别一条条来原来的代码里有个定时任务每晚同步五千条商品数据java复制下载for (Product product : productList) { productMapper.insert(product); }五千条循环插入每次都要建立一次数据库连接、解析一次SQL、刷一次磁盘。我改成了java复制下载productMapper.insertBatch(productList); // 一条SQL插入五千条配合MyBatis Plus的批量注入和rewriteBatchedStatements参数五千条插入从12秒降到了0.8秒。四、缓存是最后的防线数据访问层还有一个问题同样的字典数据、配置数据每次都去查数据库。我把这部分用Caffeine做了本地缓存TTL设置5分钟命中率直接拉满。效果前后花了一周时间从设计方案、改写代码、测试对比到灰度上线。上线后第一天的监控数据那个订单导出接口从12.8秒降到1.2秒所有涉及订单查询的接口平均响应时间下降78%数据库CPU使用率从65%降到22%定时任务的执行时间从8分钟缩短到不到2分钟产品经理再没来催过。一点思考这一周的重构本质上是在做一件事把方便换成可控。JPA很优雅但你得接受它的黑盒MyBatis啰嗦一点但每一条SQL都摆在明面上。在业务高速增长期优雅可能是负担可控才是安全感。另外不要等到接口超时才去优化。慢查询日志每周扫一遍EXPLAIN成为肌肉记忆批量操作的写法刻进代码模板——这些习惯比重构本身更重要。一周的时间换一个稳定的底层和一个不焦虑的晚上。这笔账怎么算都不亏。