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和数据库保持一致,和结论一样,可以正常执行,不会出现查询慢的情况。

总结

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

相关文章

  • Mybatis使用useGeneratedKeys获取自增主键

    Mybatis使用useGeneratedKeys获取自增主键

    这篇文章主要为大家介绍了Mybatis使用useGeneratedKeys获取自增主键示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • 解决Nacos成功启动但是无法访问 (Connection refused)

    解决Nacos成功启动但是无法访问 (Connection refused)

    这篇文章主要介绍了解决Nacos成功启动但是无法访问 (Connection refused)问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • Java将微信和支付宝支付的个二维码合二为一的方法

    Java将微信和支付宝支付的个二维码合二为一的方法

    这篇文章主要介绍了Java将微信和支付宝支付的个二维码合二为一的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 教你用Java Swing实现自助取款机系统

    教你用Java Swing实现自助取款机系统

    今天给大家带来的是关于JAVA的相关知识,文章围绕着如何用Java Swing实现自助取款机系统展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • Spring Boot企业常用的starter示例详解

    Spring Boot企业常用的starter示例详解

    这篇文章主要给大家介绍了关于Spring Boot企业常用starter的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • Java正则表达式的语法及示例解析

    Java正则表达式的语法及示例解析

    这篇文章主要介绍了Java正则表达式的语法及示例解析,需要的朋友可以参考下
    2017-07-07
  • Elasticsearch外部词库文件更新及使用

    Elasticsearch外部词库文件更新及使用

    这篇文章主要为大家介绍了Elasticsearch外部词库文件更新及使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • MyBatis-Plus Sequence主键的实现

    MyBatis-Plus Sequence主键的实现

    这篇文章主要介绍了MyBatis-Plus Sequence主键的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • SpringBoot项目里集成Hibernate的示例

    SpringBoot项目里集成Hibernate的示例

    在Spring Boot项目中,集成Hibernate可以帮助我们更轻松地进行数据库操作,本文将介绍如何在Spring Boot项目中集成Hibernate,并提供相应的示例,感兴趣的朋友跟随小编一起看看吧
    2023-04-04
  • Java开发实现的Socket双向通信功能示例

    Java开发实现的Socket双向通信功能示例

    这篇文章主要介绍了Java开发实现的Socket双向通信功能,结合实例形式分析了java基于socket实现的服务器端与客户端双向通信相关操作技巧,需要的朋友可以参考下
    2018-01-01

最新评论