mybatis查询SqlServer慢问题及解决

 更新时间:2023年08月30日 16:35:31   作者:Ikarosxx  
这篇文章主要介绍了mybatis查询SqlServer慢问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

背景

项目中用到了mybatis连接SqlServer,但遇到了一些查询慢的问题

问题1:一样的sql,换一个日期执行计划不同

# 一样的sql,djsj不同,第一条比第二条快很多
SELECT COUNT
	( 1 ) 
FROM
	e_ld2022 a WITH ( nolock )
	INNER JOIN m_user b ON b.MID = a.dbbh 
WHERE
	a.djsj = '2022-05-18 00:00:00' 
	AND a.TQBH LIKE '01%' 
	AND a.XMBH = 41;
SELECT COUNT
	( 1 ) 
FROM
	e_ld2022 a WITH ( nolock )
	INNER JOIN m_user b ON b.MID = a.dbbh 
WHERE
	a.djsj = '2022-05-19 00:00:00' 
	AND a.TQBH LIKE '01%' 
	AND a.XMBH = 41;

解决

通过MSSM分析执行计划,发现两条查询执行计划不一致,查询慢的预估行数为1,走了LOOP,循环次数过多导致变慢

故怀疑是没有更新统计信息,导致优化器优化失败

# 更新统计信息
UPDATE STATISTICS databse.table;

执行更新统计信息后重新查询,正常。

问题2:#{}和${}导致查询效率不同

mybatis中使用到了如下语句

select a.*,x.CBX from e_ld${year} a inner join E_XM x on x.XMBH = a.XMBH
<where>
	<if test="dbbh != null and dbbh !=''">
		AND dbbh LIKE concat(#{dbbh},'%')
	</if>
	<if test="tqbh != null and tqbh !=''">
		AND TQBH LIKE concat(#{tqbh},'%')
	</if>
</where>

经过测试,只要条件增加了DBBH和TQBH,就是LIKE语句,查询就巨慢

但一样的SQL拎出来放到MSSM上执行,就很快

解决

经过偶然测试,发现如果使用AND TQBH LIKE '${tqbh}%',就很快

说明问题出现在${}与#{}的区别上

以往的认知上,只知道#{}就相当于PreparedStatement,能够防注入

${}可能出现注入风险

但不知道为啥这个会影响到查询性能

跟了一下源码,发现跟sendStringParametersAsUnicode和数据库字段类型(VARCHAR、NVARCHAR)有关系

总结来说就是

sendStringParametersAsUnicode\字段类型VARCHARNVARCHAR
true×
false×

分析

SendStringParametersAsUnicode文档

SendStringParametersAsUnicode={true | false}.

Determines whether string parameters are sent to the SQL Server databasein Unicode or in the default character encoding of the database.

True means that string parameters are sent to SQL Serverin Unicode.

False means that they are sent in the default encoding, which can improve performance because the serverdoes not need to convert Unicode characters to the default encoding.

You should, however, use default encoding only if theparameter string data that you specify is consistent with the default encoding of the database.The default is true.

如果SendStringParametersAsUnicode=true,会将String参数用Unicode的编码方式发送个服务器,即 JDBCType=NVARCHAR

如果SendStringParametersAsUnicode=false,会将String参数用默认的方式发送给服务器,即 JDBCType=VARCHAR

我们系统里 SendStringParametersAsUnicode=false ,所以指定的 JdbcType=VARCHAR

但是数据库字段是NVARCHAR,和我们指定的不一致,所以会发生转换性能损耗,导致时间查询慢

基于这个思路,我测试了一下

select a.*,x.CBX from e_ld${year} a inner join E_XM x on x.XMBH = a.XMBH
<where>
	<if test="dbbh != null and dbbh !=''">
		AND dbbh LIKE concat(#{dbbh, jdbcType=NVARCHAR},'%')
	</if>
	<if test="tqbh != null and tqbh !=''">
		AND TQBH LIKE concat(#{tqbh, jdbcType=NVARCHAR},'%')
	</if>
</where>

在mybatis xml中手动指定参数的jdbcType和数据库保持一致,和结论一样,可以正常执行,不会出现查询慢的情况。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • springboot自动重启的简单方法

    springboot自动重启的简单方法

    Springboot提供了热部署的方式,当发现任何类发生了改变,马上通过JVM类加载的方式,加载最新的类到虚拟机中。这篇文章主要介绍了springboot自动重启的实现方法,需要的朋友可以参考下
    2018-04-04
  • Sentinel热点规则示例详解分析

    Sentinel热点规则示例详解分析

    这篇文章主要介绍了何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制
    2021-09-09
  • 针对Dubbo接口Mock的解决方案详解

    针对Dubbo接口Mock的解决方案详解

    这篇文章主要为大家介绍了针对Dubbo接口Mock的解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Java创建文件且写入内容的方法

    Java创建文件且写入内容的方法

    这篇文章主要介绍了Java创建文件且写入内容的方法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • Java使用JDBC驱动连接MySQL数据库

    Java使用JDBC驱动连接MySQL数据库

    这篇文章主要为大家详细介绍了Java使用JDBC驱动连接MySQL数据库的具体步骤,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • SpringMVC配置多个properties文件之通配符解析

    SpringMVC配置多个properties文件之通配符解析

    这篇文章主要介绍了SpringMVC配置多个properties文件之通配符解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Spring BPP中如何优雅的创建动态代理Bean详解

    Spring BPP中如何优雅的创建动态代理Bean详解

    这篇文章主要给大家介绍了关于Spring BPP中如何优雅的创建动态代理Bean的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • Java中字符序列的替换与分解的几种实现方法

    Java中字符序列的替换与分解的几种实现方法

    本文主要介绍了Java中字符序列的替换与分解的几种实现方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • SpringBoot集成mybatis实例

    SpringBoot集成mybatis实例

    本篇文章主要介绍了SpringBoot集成mybatis实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • Spring动态管理定时任务之ThreadPoolTaskScheduler解读

    Spring动态管理定时任务之ThreadPoolTaskScheduler解读

    这篇文章主要介绍了Spring动态管理定时任务之ThreadPoolTaskScheduler解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12

最新评论