在现代企业级应用开发中,MyBatis作为主流的持久层框架,其性能直接影响系统响应速度。本文结合最新实践案例,总结MyBatis及MyBatis-Plus的优化策略,帮助开发者规避常见性能陷阱。
一、SQL语句优化:从源头减少损耗
-
精准查询字段
避免使用SELECT *
,仅查询业务所需字段。通过<sql>
标签定义可复用字段集合,结合<include>
引用,减少重复书写。例如:<sql id="base_fields">id, name, status, create_time</sql> <select id="selectUsers" resultType="User"> SELECT <include refid="base_fields"/> FROM user WHERE status = #{status} </select>
-
动态条件优化
• 使用<if>
标签时,优先通过Service层预处理参数,减少动态SQL复杂度。
• 避免在IN
子句中传递超过1000个参数,建议分批处理或改用临时表。
• 用DECODE
或CASE WHEN
替代复杂<choose>
逻辑,减少SQL膨胀和硬解析。 -
批量操作合并
使用<foreach>
生成批量插入/更新语句,减少数据库交互次数。例如:<insert id="batchInsert"> INSERT INTO user (id, name) VALUES <foreach collection="list" item="user" separator=","> (#{user.id}, #{user.name}) </foreach> </insert>
二、缓存策略:平衡效率与一致性
-
一级缓存(SqlSession级)
默认开启,需配合@Transactional
注解生效。适用于单事务内重复查询场景。 -
二级缓存(Mapper级)
需配置mybatis.configuration.cache-enabled=true
并添加@CacheNamespace
注解。注意:不推荐跨Mapper共享热点数据,易引发缓存雪崩。 -
三级缓存(分布式场景)
在二级缓存基础上集成Redis,通过@Cacheable
注解实现跨服务缓存一致性。
三、分页性能优化:避免深分页陷阱
-
插件选择与配置
使用MyBatis-Plus的PaginationInterceptor
或PageHelper,生成带LIMIT
的SQL。建议设置count=false
跳过统计总记录数。 -
自定义COUNT查询
对复杂查询重写COUNT逻辑,仅统计主表数据。例如:<!-- 原分页查询 --> <select id="selectByCondition" resultMap="BaseResultMap"> SELECT a.*, b.field FROM table_a a LEFT JOIN table_b b ON a.id = b.aid WHERE a.status = #{status} </select> <!-- 自定义COUNT查询 --> <select id="selectByCondition_COUNT" resultType="Long"> SELECT COUNT(DISTINCT a.id) FROM table_a a WHERE a.status = #{status} </select>
四、框架配置优化:连接池与监控
-
连接池参数调优
推荐使用HikariCP或Druid,配置核心参数:spring.datasource.hikari.maximum-pool-size=20 spring.datasource.hikari.minimum-idle=5
-
集成监控工具
通过Druid监控SQL执行时间,识别慢查询。配置示例:@Bean public ServletRegistrationBean<StatViewServlet> druidStatViewServlet() { return new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); }
五、拦截器与插件优化:警惕长SQL拼接
典型案例:某项目因MyBatis-Plus租户拦截器拼接超长SQL(含上千个IN
参数),导致单次查询耗时从几十ms飙升至1秒。
解决方案:
- 使用
@InterceptorIgnore
注解忽略非必要拦截器。 - 自行拼接动态条件,避免插件处理长SQL。
- 对长列表分批查询,减少单次占位符数量。
其他注意事项
-
注释处理
避免在SQL中使用--
注释,改用XML注释<!-- -->
,防止分页插件解析错误。 -
参数类型匹配
确保Java实体类字段类型与数据库严格对应(如java.util.Date
对应OracleDATE
),避免隐式转换开销。 -
日志级别控制
生产环境关闭MyBatis详细日志(log4j.logger.org.mybatis=ERROR
),减少IO开销。
总结
MyBatis性能优化需从SQL编写、缓存策略、框架配置多维度入手。对于复杂场景,建议结合EXPLAIN PLAN
分析执行计划,并通过Arthas等工具定位性能瓶颈。通过上述优化,可显著提升系统吞吐量,降低响应延迟。