MyBatis 性能优化:批处理、分页、缓存与慢 SQL 定位

目标:你能把 MyBatis 的性能问题拆成"SQL 本身 + JDBC/网络 + MyBatis 使用方式"三层,并掌握可落地的优化点。

1. 性能问题先分层:不要一上来就调 MyBatis

MyBatis 慢,常见根因优先级通常是:

  1. SQL/索引设计(占大头)
  2. 连接池/网络/DB 负载
  3. MyBatis 使用方式(N+1、错误分页、批处理不当)

面试时你要体现"先定位再优化"的工程能力。

2. N+1 问题:最常见的 ORM 性能坑

典型场景:

  • 查主表 N 条,再对每条查一次明细表
  • 日志里表现为一堆重复 SQL

解决方案:

  • 一次性 join 或 IN 批量查询
  • 用 resultMap 做聚合映射(注意去重)
  • 业务层做批量预取

排查手段:

  • 打开 SQL 日志,观察是否出现"同模板 SQL 重复执行 N 次"
  • 用链路追踪看 DB span 数量是否异常

3. 分页:你以为用了分页,其实在内存分页

3.1 正确分页:让 DB 做 limit/offset 或基于游标

  • limit offset, size 简单但 offset 大时会慢
  • 大翻页建议:
    • 基于主键/索引的"seek"方式(where id > lastId limit size)

3.2 常见坑:不小心触发全量查询

  • 没有加 limit
  • PageHelper/拦截器没生效(配置顺序、插件冲突)

排查:

  • 看最终发到 DB 的 SQL 是否有 limit

4. 批处理:减少网络往返,但别把内存打爆

4.1 批处理的收益

  • 单条插入 1000 次 = 1000 次网络往返
  • 批处理 = 1 次或少量往返

4.2 常见误区

  • 一次攒太大批次:
    • MyBatis/JDBC 会缓存参数,容易占用大量内存
  • 没有控制事务:
    • 批处理通常应显式事务,否则每条 auto-commit 性能差

建议:

  • 分批提交(例如 500/1000 一批)
  • 明确事务边界
  • 监控单次批处理耗时与失败重试策略

5. 缓存:一级缓存别神化,二级缓存要谨慎

5.1 一级缓存(SqlSession 级别)

  • 同一个 SqlSession 内重复查询可命中
  • 默认开启

坑:

  • 与事务/会话生命周期强相关
  • 在 Web 应用中通常每次请求一个 SqlSession,收益有限

5.2 二级缓存(Mapper 级别)

  • 跨 SqlSession
  • 需要显式开启,且对象要可序列化

风险:

  • 一致性:更新后缓存失效策略复杂
  • 命中率:命中低反而多一次序列化开销

建议:

  • 更推荐把缓存放到 Redis/本地缓存层,用更可控的失效策略
  • 二级缓存只用于少量稳定读、低写场景

6. 慢 SQL 定位:从 MyBatis 到数据库的闭环

6.1 你需要的三类证据

  • 应用侧:SQL 模板、参数、耗时、调用栈
  • DB 侧:慢日志、执行计划、锁等待
  • 链路侧:某接口中 DB 调用次数与分布

6.2 常见慢因

  • 索引失效(隐式类型转换、函数包裹列、like 前缀 %)
  • 返回列过多(select *)
  • 大 offset 分页
  • 锁等待(更新热点行)

6.3 MyBatis 相关的定位点

  • 是否存在大量小 SQL(N+1)
  • 是否事务过大导致锁持有时间长
  • 是否执行了不必要的 flush

7. 参数与映射:性能与正确性的隐形成本

  • 大字段(TEXT/BLOB)不要随意查出来
  • 合理使用延迟加载(谨慎:容易触发 N+1)
  • resultMap 的嵌套映射要注意去重与集合膨胀

8. 面试背诵稿(45 秒)

MyBatis 性能优化我会先分层:优先看 SQL 和索引,再看连接池与 DB 负载,最后才是 MyBatis 使用方式。

最常见的问题是 N+1,我会用 join 或 IN 批量预取解决;分页要确保最终 SQL 带 limit,并且大翻页用基于索引的 seek 分页。

批处理能显著减少网络往返,但要控制批次大小并明确事务边界避免内存膨胀。

缓存方面一级缓存作用受 SqlSession 生命周期限制,二级缓存一致性成本高,通常更建议用独立缓存层。

定位慢 SQL 时要把应用侧 SQL+参数、DB 执行计划和链路调用次数三类证据闭环。

相关推荐
黄俊懿8 小时前
【架构师从入门到进阶】第六章:服务集群优化——第八节:线程数公式
java·服务器·数据库·分布式·性能优化·架构·系统架构
步步为营DotNet10 小时前
Async 状态机要搬进运行时了:.NET 10 Runtime Async 实测,快的地方快 1.5 倍,贵的地方贵 5 倍
性能优化·c#·.net·async·runtime
Chenyu_31020 小时前
DPDK、TC 和 XDP:Linux 高性能网络到底在优化什么
linux·服务器·网络·缓存
CCblandy21 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
Highcharts.js1 天前
Highcharts 发布16项最新安全公告
人工智能·安全·性能优化·highcharts·可视化图表
我不会起名字3221 天前
MySQL 深分页 LIMIT 1000000 卡死:3 种改写与 4 组实测对比
mysql·性能优化·索引·分页·limit
加宝的起点雷达1 天前
扩散语言模型跑出 2788 tokens/s,单卡就够,怎么做到的
人工智能·性能优化
CCblandy1 天前
向量检索 ANN 参数实测:换一种数据分布,recall 掉了 51 个百分点
人工智能·python·算法·自然语言处理·性能优化
Highcharts.js1 天前
Highcharts 数据过滤实战指南:从基础实现到性能优化
javascript·性能优化·bi·highcharts·前端可视化·数据过滤·交互图表
毕业设计7031 天前
(免费领源码)SSM董家湾线上点餐系统04682- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·redis·mysql·tomcat·maven·mybatis·ssm