网站首页 > 博客文章 正文
前言:为什么你的MyBatis这么慢?
MyBatis作为Java生态中最流行的ORM框架之一,被广泛应用于各类项目中。然而,很多开发者在享受其灵活性的同时,却常常遭遇性能瓶颈。本文将全面剖析MyBatis慢查询的根源,并提供可直接落地的优化方案。
一、SQL查询基础优化
1.1 避免SELECT * 查询
<!-- 反例 -->
<select id="getUser" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 正例 -->
<select id="getUser" resultType="User">
SELECT id, username, email FROM user WHERE id = #{id}
</select>
优化效果:减少网络传输量和内存占用,提升20-50%查询速度
1.2 合理使用索引
// 反例:对非索引列进行条件查询
@Select("SELECT * FROM orders WHERE status = #{status} AND create_time > #{time}")
List<Order> findOrdersByStatusAndTime(@Param("status") String status, @Param("time") Date time);
// 正例:确保查询条件使用索引列
@Select("SELECT * FROM orders WHERE order_id = #{orderId} AND user_id = #{userId}")
Order findOrderByIds(@Param("orderId") Long orderId, @Param("userId") Long userId);
关键点:使用EXPLAIN分析SQL执行计划,确保查询走索引
二、MyBatis高级特性优化
2.1 动态SQL性能陷阱
<!-- 反例:过度使用动态SQL导致执行计划不稳定 -->
<select id="findUsers" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="email != null">
AND email = #{email}
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
</select>
<!-- 正例:使用固定查询+业务层过滤 -->
<select id="findActiveUsers" resultType="User">
SELECT id, name, email FROM user WHERE status = 'ACTIVE'
</select>
优化建议:超过3个动态条件应考虑拆分查询或使用搜索引擎
2.2 批量操作优化
// 反例:循环单条插入
@Insert("INSERT INTO user(name,email) VALUES(#{name},#{email})")
void insertUser(User user);
// 正例:使用批量插入
@Insert("<script>" +
"INSERT INTO user(name,email) VALUES " +
"<foreach collection='users' item='user' separator=','>" +
"(#{user.name},#{user.email})" +
"</foreach>" +
"</script>")
void batchInsert(@Param("users") List<User> users);
性能对比:批量插入比单条循环插入快10-100倍
三、缓存机制深度优化
3.1 一级缓存失效场景
// 反例:同一会话中重复查询但中间有更新操作
User user1 = userMapper.getUser(1L); // 查询数据库
userMapper.updateUser(user); // 清空一级缓存
User user2 = userMapper.getUser(1L); // 再次查询数据库
// 正例:合理利用一级缓存
SqlSession session1 = sqlSessionFactory.openSession();
try {
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.getUser(1L); // 查询数据库
User user2 = mapper1.getUser(1L); // 使用缓存
} finally {
session1.close();
}
缓存规则:一级缓存作用范围为SqlSession,任何UPDATE操作都会清空缓存
3.2 二级缓存配置优化
<!-- 启用二级缓存并配置参数 -->
<cache
eviction="LRU"
flushInterval="60000"
size="1024"
readOnly="true"/>
<!-- 特定语句禁用二级缓存 -->
<select id="getRealTimeData" useCache="false">
SELECT * FROM realtime_data WHERE id = #{id}
</select>
最佳实践:
- 读多写少的数据适合缓存
- 实时性要求高的数据禁用缓存
- 设置合理的刷新间隔和淘汰策略
四、结果集处理优化
4.1 避免大结果集内存溢出
// 反例:一次性加载百万数据
@Select("SELECT * FROM big_data")
List<BigData> getAllBigData();
// 正例:使用游标分批处理
@Select("SELECT * FROM big_data")
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
Cursor<BigData> getBigDataCursor();
处理建议:结果集超过1万条应考虑流式处理或分页
4.2 复杂结果集映射优化
<!-- 反例:N+1查询问题 -->
<resultMap id="userWithOrders" type="User">
<collection property="orders" column="id"
select="com.example.mapper.OrderMapper.findByUserId"/>
</resultMap>
<!-- 正例:使用JOIN一次查询 -->
<resultMap id="userWithOrders" type="User">
<id property="id" column="user_id"/>
<collection property="orders" ofType="Order">
<id property="id" column="order_id"/>
<!-- 其他字段映射 -->
</collection>
</resultMap>
<select id="getUserWithOrders" resultMap="userWithOrders">
SELECT u.*, o.*
FROM user u LEFT JOIN orders o ON u.id = o.user_id
WHERE u.id = #{id}
</select>
性能对比:JOIN方式比N+1查询快5-10倍
五、连接池与配置优化
5.1 连接池参数配置
# HikariCP推荐配置(根据服务器配置调整)
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
监控指标:
- 连接获取平均时间应<100ms
- 活跃连接数不应长期接近最大连接数
5.2 MyBatis全局配置
<settings>
<!-- 开启驼峰命名转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 禁用延迟加载的激进模式 -->
<setting name="aggressiveLazyLoading" value="false"/>
<!-- 设置默认执行器类型 -->
<setting name="defaultExecutorType" value="REUSE"/>
</settings>
关键参数:
- defaultExecutorType:REUSE比SIMPLE节省10-15%开销
- localCacheScope:STATEMENT级别可减少内存占用
六、监控与诊断方案
6.1 慢查询日志
@Intercepts({
@Signature(type= Executor.class, method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type= Executor.class, method="query",
args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
})
public class SqlCostInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = invocation.proceed();
long end = System.currentTimeMillis();
if(end - start > 1000) { // 超过1秒记录警告
log.warn("Slow SQL detected: cost {}ms", end - start);
}
return result;
}
}
6.2 可视化监控方案
推荐工具:
- Prometheus + Grafana监控SQL执行指标
- Arthas诊断运行时性能问题
- SkyWalking分布式链路追踪
结语:性能优化永无止境
MyBatis性能优化需要从SQL编写、框架配置、缓存策略、监控体系等多个维度综合考虑。本文提供的方案已在生产环境验证,可帮助系统提升3-10倍数据库访问性能。记住:没有放之四海皆准的最优配置,持续监控和调优才是王道。
猜你喜欢
- 2025-06-03 程序员简历例句—范例Java、Python、C++模板
- 2025-06-03 SQLREST工具的功能概述及使用指南
- 2025-06-03 SpringBoot一个提升N倍性能的操作
- 2025-06-03 Jeecgboot3.2版-postgres脚本制作
- 2025-06-03 心心念念的前端代码生成利器,前后端一网打尽
- 2025-06-03 基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构(附源码)
- 2025-06-03 有了 SPL,看来用不着 ORM 了(spl使用)
- 2025-06-03 Gradle的学习(gradle入门到精通)
- 2025-06-03 SpringBoot整合MybatisPlus实现分页查询
- 2025-06-03 SpringBoot、MyBatis、Vue搭建一个Java企业应用开源框架源码分享
你 发表评论:
欢迎- 07-08Google Cloud Platform 加入支持 Docker 的容器引擎
- 07-08日本KDDI与Google Cloud 签署合作备忘录,共探AI未来
- 07-08美国Infoblox与Google Cloud合作推出云原生网络和安全解决方案
- 07-08GoogleCloud为Spanner数据库引入HDD层,将冷存储成本降低80%
- 07-08谷歌推出Cloud Dataproc,缩短集群启动时间
- 07-08Infovista与Google Cloud携手推进射频网络规划革新
- 07-08比利时Odoo与Google Cloud建立增强合作,扩大全球影响力
- 07-08BT 和 Google Cloud 通过 Global Fabric 加速 AI 网络
- 最近发表
-
- Google Cloud Platform 加入支持 Docker 的容器引擎
- 日本KDDI与Google Cloud 签署合作备忘录,共探AI未来
- 美国Infoblox与Google Cloud合作推出云原生网络和安全解决方案
- GoogleCloud为Spanner数据库引入HDD层,将冷存储成本降低80%
- 谷歌推出Cloud Dataproc,缩短集群启动时间
- Infovista与Google Cloud携手推进射频网络规划革新
- 比利时Odoo与Google Cloud建立增强合作,扩大全球影响力
- BT 和 Google Cloud 通过 Global Fabric 加速 AI 网络
- NCSA和Google Cloud合作开发AI驱动的网络防御系统,加强泰国网络空间的安全性
- SAP将在沙特阿拉伯 Google Cloud 上推出BTP服务
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- messagesource (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)