Mybatis-Plus执行超长SQL性能问题排查

问题描述

项目上使用了Mybatis-Plus,发现部分接口性能很差,经常会超过30s导致响应超时。接口里边有很大的一个SQL,里边in条件塞了上千个user_id,本以为是这个sql导致的性能问题,后来发现SQL执行只花了几十ms。排查了几天终于发现了问题。

问题原因

我们使用了Mybatis-Plus的租户拦截器TenantLineInnerInterceptor,在SQL语句上自动拼接了tenant_id、appBuId这两个查询条件。排查发现,mapper接口对应的SQL如果很长,TenantLineInnerInterceptor拦截器拼接租户id的查询条件会有很严重的性能问题,SQL本身执行只需要几十毫秒,但拼接这个租户id的查询条件花了6、700ms;因为我们定义了两个TenantLineInnerInterceptor拦截器,所以一条SQL拼接查询条件,至少要1s多。最后使用Mybatis-Plus自带的@InterceptorIgnore注解,忽略租户Id的拦截器,自行组装查询条件,就不会有性能问题了。

排查过程

  1. 一开始认为是in条件里边参数太多,导致性能太差。后来发现sql语句执行其实很快,说明不是这个原因。
  2. 猜测是打印日志太长引起的,
    1. 关闭mybatis、mybatis-plus日志打印,控制台还是输出了
    2. 替换为mybatis最原始的数据源配置,不用动态数据源了,日志就不输出了,说明是打印日志是动态数据源的打印的
    3. 但接口耗时还是很长
  3. 猜测是mybatis或者mybatis-plus预编译SQL,传入的in条件的参数太多,替换?占位符太多导致耗时长。
    1. 使用JDBC执行写死的SQL,速度正常;
    2. 新写了一个mapper方法,不传入参数,SQL语句也写死,不需要组装in条件的参数
    3. mapper方法耗时还是很长,使用了hutool的StopWatch来计算方法耗时
  4. 不清楚是Mybatis还是Mybatis-Plus的问题,于是我创建了一个新项目,里边只引用了Mybatis,也是mapper方法也是写死SQL,发现执行耗时是正常的。
  5. 那就确认是Mybatis-Plus的问题了,猜测是mybatis-plus的拦截器插件引起的,项目上使用了3个插件,乐观锁、分页、多租户插件,其中多租户使用了两次。
    1. 把mybatis拦截器里边逐个拦截器注释,看看mapper方法耗时;发现租户ID和appBuId的拦截器,注释掉后性能正常了,每多一个,耗时多600ms;到此定位到问题了。
  6. 由于项目是SaaS系统,这个租户id拦截器是必须要加的,而且大部分SQL都没有性能问题,只有少数这几个in条件参数太多耗时长的问题。在Mybatis-Plus官网上找到了忽略拦截器的注解,加上之后,SQL耗时就正常了
  7. 排查Mybatis-Plus源码,使用Arthas查看方法内部调用路径,并输出方法路径上的每个节点上耗时,MybatisPlusInterceptor是所有插件的核心。trace com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor intercept,可以看到主要耗时在beforeQuery方法上。trace com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor beforeQuery最后排查到是一个工具类JSqlParserUtil的parse方法耗时太长,这个来自于jsqlparser的第三方jar包,也不是Mybatis-Plus的代码,这块代码看不懂,就不再深究下去了……

总结 

Mybatis-Plus的租户拦截器,在遇到超长SQL的时候,拼接租户id的查询条件会有性能问题,这种场景可以单独使用 @InterceptorIgnore拦截忽略注解,忽略租户id的拼接,然后自行在SQL上添加这个租户id的查询条件,接口性能就正常了。

在使用Spring Boot与MyBatis-Plus连接SQL Server时,可能会遇到以下问题: 1. 驱动问题:首先需要引入SQL Server的JDBC驱动,可以在pom.xml文件中添加依赖。常用的驱动有`com.microsoft.sqlserver.jdbc.SQLServerDriver`和`net.sourceforge.jtds.jdbc.Driver`。确保驱动版本与SQL Server版本兼容。 2. 数据库连接配置:在application.properties或application.yml文件中,需配置SQL Server的连接信息,包括数据库地址、端口、用户名、密码等。注意要正确配置驱动名称、连接URL以及字符集等。 3. 数据库版本兼容性:确保使用的SQL Server版本与MyBatis-Plus和JDBC驱动兼容。不同版本的SQL Server可能在SQL语法、特性或驱动接口上有所区别。 4. 数据库表映射:在使用MyBatis-Plus进行ORM映射时,需要在实体类中使用注解配置数据表名、字段名和主键等信息。同时,要确认实体类和数据表的字段类型、长度、精度等匹配。 5. 数据库连接池配置:可以使用Spring Boot提供的连接池技术,如HikariCP或Tomcat连接池。根据并发需求和性能要求,配置合适的连接池大小、最大等待时间和最大空闲时间等参数。 6. 异常处理与日志记录:在连接SQL Server过程中,可能会出现连接异常、语法错误等问题。需要适当处理这些异常,并进行日志记录以便排查和分析问题。 通过解决上述问题,我们可以成功连接SQL Server数据库,并使用MyBatis-Plus进行数据操作和ORM映射。持续的测试和调试可以保证系统的稳定性和性能
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值