接口响应变慢、数据库负载上升时,“把系统拆成几个服务”听起来像一种直接的解决办法。但如果拆分后的服务仍然执行同样的低效查询,甚至增加跨服务调用,原有瓶颈可能继续存在。应先找到资源消耗和等待发生的位置,再决定改造层级。
一、用具体请求定义性能问题
不要只写“数据库慢”。记录哪些接口、哪些时间段、什么数据范围和并发条件下出现问题,再观察中位数与高分位耗时、超时和错误情况。尤其要区分持续退化、流量高峰和定时任务重叠等不同情形。
先挑一个影响重要业务且能够复现的请求,追踪入口、应用处理、数据库和外部依赖。接口慢不一定全部耗在数据库,也可能在等待连接、锁、其他接口或应用资源。
二、看实际 SQL,而不只看应用代码
无论使用 EF Core、SqlSugar 还是手写 SQL,都需要检查实际发送的语句、参数特征、返回行数及执行计划。重点核查是否只取必要字段、是否存在循环查询、分页是否合理,以及索引是否适合实际过滤与排序方式。
微软的 EF Core 高效查询指南讨论了索引使用、按需投影、限制结果集和额外往返等问题。这些是排查数据访问的重要切入点,但具体措施需要结合数据库与查询证据验证。参见EF Core 高效查询指南。
三、把锁等待和连接等待单独检查
查询执行慢、等待锁、等待可用连接不是同一种问题。检查事务中是否包含不必要的远程调用或长时间处理,连接是否及时释放,以及应用并发是否超出数据库当前承载能力。单纯增大连接池上限可能把更多请求同时推向数据库。
- 关键语句实际处理多少行,返回多少行?
- 慢请求是否集中在某类参数或特定客户的数据范围?
- 批处理、报表和在线业务是否在争用相同资源?
- 失败重试是否放大了已经出现的负载?
四、先修可验证的问题,再引入新的数据路径
根据证据评估查询调整、索引、批量处理、事务缩短或任务错峰。每次变更应检查收益和副作用,例如索引增加可能影响写入与存储,批量化可能改变事务时长。用相同测试条件和业务数据分布做前后比较。
需要缓存时,明确允许的数据陈旧程度、失效方式及缓存不可用时的处理;考虑只读副本时,评估复制延迟和读取一致性要求;考虑数据拆分时,明确数据所有权与迁移方案。它们都不是不需要维护成本的开关。
五、什么时候才把问题提升到架构层面?
如果经过排查,某类业务确实需要独立扩展、与其他负载隔离,或者共享数据边界已经阻碍长期演进,可以进一步比较服务拆分与数据架构调整。但应说明新方案具体消除了什么竞争或依赖,并验证迁移与故障恢复方式。
“上线后感觉快了”不足以作为结论。应记录测试环境、负载、数据规模、响应指标、错误情况与资源消耗,避免用不同条件制造改善结果。
如果团队无法确定瓶颈属于查询、部署容量还是服务边界,可以从系统架构诊断开始,围绕一条关键业务路径形成证据、调整建议与验证计划,再决定是否投入更大范围的微服务改造。