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 执行计划和链路调用次数三类证据闭环。

相关推荐
ward RINL8 小时前
redis分页查询
数据库·redis·缓存
oLLI PILO9 小时前
Redis连接池
数据库·redis·缓存
热爱Java,热爱生活10 小时前
浅谈Spring三级缓存
java·spring·缓存
heRs BART10 小时前
Redis简介、常用命令及优化
数据库·redis·缓存
蒸汽求职10 小时前
破局“无效互面”:跨国大厂视角的工业级 Mock Interview 价值解析
缓存·面试·职场和发展·金融·notion
cwxcc11 小时前
Google Core Web Vitals(核心网页指标)
前端·性能优化
Irissgwe11 小时前
redis之常见数据类型
数据库·redis·缓存
花椒技术11 小时前
从7S到4S,我们如何系统性降低直播播放延迟
性能优化·程序员
DROm RAPS12 小时前
redis 配置
数据库·redis·缓存
SeSs IZED13 小时前
Redis开启远程连接
数据库·redis·缓存