谨慎使用MyBatis自动生成Where语句
最近监控到类似这样一个慢查询:
select XX_time
from XXOrderInfo
WHERE ( OrderId is not null and
OrderId = N'xxxx')
xxOrderInfo表上有一个OrderId的索引,但OrderId字段是Varchar类型。
由于开发框架MyBatis自动生成Where条件不会指定参数类型,字符串类型的参数到了SQLServer里就自动成了NVARCHAR(4000)类型了,
坑人的是,不指定参数类型也就罢了,还自动加了个OrderId Is NOT NULL这样一个非SARG的条件,执行计划成了这样:
---------------------------------------------------------------------------------------------
如果没有OrderId IS NOT NULL这个条件,执行计划会是这样的:
由于参数类型Nvarchar比索引字段类型varchar优先级要高,不能直接转换,但SQLServer优化器最终还是将他转成了一个范围值,最终的等号查询也变成了类似一个小范围查询。
可以从Index Seek这一步的详细信息可以看出:
------------------------------------------------------------------------
如果参数类型匹配,那么执行计划会是想象中的那样(虽然没有包含到,还是有Key Lookup):
--------------------------------------------------------------------------------------
当然,有点小小强迫症的我最终希望的写法是这样的:
select XXXX_time
from XXOrderInfo
WHERE OrderId = 'xxxx'
执行计划当然也会是这样的:
只是,只是不知道最终开发大神能改成什么样......
---------------------------------------------------------------
开发大神的解决方案:连接字符串中配置:sendStringParametersAsUnicode=false
---------------------------------------------------------------
后记:
默认情况下,Java 中的字符数据作为 Unicode 进行处理;Java String 对象表示 Unicode 字符数据。在 JDBC 驱动程序中,唯一可以不遵守此规则的是 ASCII 流 getter 和 setter 方法,这属于比较特殊的情况,因为这些方法使用的字节流带有单个已知代码页 (ASCII) 的隐式假定。
此外,JDBC 驱动程序提供了 sendStringParametersAsUnicode 连接字符串属性。此属性可用于指定作为 ASCII 而不是 Unicode 来发送的字符数据的预定义参数。
作为性能方面的一项增强功能,可以通过设置 sendStringParametersAsUnicode 连接字符串属性将 String 参数以非 Unicode 格式传递到 SQL Server。
如果 sendStringParametersAsUnicode 属性设置为“true”,String 参数将以 Unicode 格式发送到服务器。
如果 sendStringParametersAsUnicode 属性设置为“false”,String 参数将以非 Unicode 格式(如 ASCII/MBCS )而不是 Unicode 格式发送到服务器。
sendStringParametersAsUnicode 属性的默认值为“true”。 Note: 仅在使用 CHAR、VARCHAR 或 LONGVARCHAR JDBC 类型发送参数时检查.sendStringParametersAsUnicode 属性。 新的 JDBC 4.0 国家字符方法(例如 SQLServerPreparedStatement 和 SQLServerCallableStatement 类的 setNString、setNCharacterStream 和 setNClob 方法)始终将它们的参数值以 Unicode 格式发送到服务器,而不考虑此属性的设置。
为了使 CHAR、VARCHAR 和 LONGVARCHAR JDBC 数据类型获得最佳性能,应用程序应将 sendStringParametersAsUnicode 属性设置为“false”并使用 SQLServerPreparedStatement 和 SQLServerCallableStatement 类的 setString、setCharacterStream 和 setClob 非国家字符方法。 当应用程序将 sendStringParametersAsUnicode 属性设置为“false”并使用非国家字符方法访问服务器端(如nchar、nvarchar 和 ntext)上的 Unicode 数据类型时,如果数据库排序规则不支持非国家字符方法传递的 String 参数中的字符,则某些数据可能丢失。 请注意,对于NCHAR、NVARCHAR 和 LONGNVARCHAR JDBC 数据类型,应用程序应使用 SQLServerPreparedStatement 和 SQLServerCallableStatement 类的 setNString、setNCharacterStream 和 setNClob 国家字符方法。
参考:
http://d.hatena.ne.jp/gnarl/20110706/1309945379
https://technet.microsoft.com/zh-cn/library/ms378857(SQL.110).aspx
https://technet.microsoft.com/zh-cn/library/ms378988(v=sql.110).aspx
谨慎使用MyBatis自动生成Where语句的更多相关文章
- springboot+mybatis+mysql 利用mybatis自动生成sql语句
工具和环境 idea,mysql,JDK1.8 效果图如下 结构图如下 java resources sql文件 /* Navicat MySQL Data Transfer Source Serve ...
- 【MyBatis】MyBatis自动生成代码查询之爬坑记
前言 项目使用SSM框架搭建Web后台服务,前台后使用restful api,后台使用MyBatisGenerator自动生成代码,在前台使用关键字进行查询时,遇到了一些很宝贵的坑,现记录如下.为展示 ...
- Mybatis自动生成实体类
Maven自动生成实体类需要的jar包 一.pom.xml中 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns ...
- 使用mybatis-generator插件结合tk.mybatis自动生成mapper二三事
本篇文章将介绍使用spring boot框架,引入mybatis-generator插件,结合tk.mybatis自动生成Mapper和Entity的一整套流程,其中包括最重要的踩坑与填坑. ...
- mybatis自动生成代码工具(逆向工程)
MyBatis自动生成实体类(逆向工程) MyBatis属于一种半自动的ORM框架,它需要我们自己编写sql语句和映射文件,但是编写映射文件和sql语句很容易出错,所以mybatis官方提供了Gene ...
- 使用mybatis-generator插件结合tk.mybatis自动生成mapper
本篇文章将介绍使用spring boot框架,引入mybatis-generator插件,结合tk.mybatis自动生成Mapper和Entity的一整套流程,其中包括最重要的踩坑与填坑. ...
- mybatis自动生成java代码
SSM框架没有DB+Record模式,写起来特别费劲,只能用下面的方法勉强凑合. 上图中,*.jar为下载的,src为新建的空白目录,.xml配置如下. <?xml version=" ...
- 使用Excel自动生成sql语句
在近一段日子里,进入了新的项目组,由于项目需要,经常要将一些Excel表中的数据导入数据库中,以前并没有过多的接触过数据导入与数据处理,对于我来说比较痛苦,今天下午花了几个小时处理数据,但是同事给我提 ...
- Mybatis 自动生成代码,数据库postgresql
最近做了一个项目,使用Mybatis自动生成代码,下面做一下总结,被以后参考: 一.提前准备: 1.工具类:mybatis-generator-core-1.3.2.jar 2.postgresql驱 ...
随机推荐
- JavaScript初探一
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- Unity3D中的常用方法
备注:文中所使用的this均指脚本所依附的对象 1.移动(用Translate方法进行移动) ; //移动速度 this.transform.Translate(Vector3.down * Time ...
- 文件句柄FileDescriptor的hanle/fd两个字段分析
对于FileInputStream/FileOutputStream/RandomAccessFile,使用handle来表示底层的文件句柄 对于ServerSocket/Socket,使用fd来表示 ...
- solr(一) : 整合 tomcat
前面 lucene 初探 都是为了solr打基础的. 虽然lucene 的filter 没有涉及, 但是打基础, 差不多够用了. 一. solr 和 lucene 的区别 这里我就用自己的理解来说了, ...
- php的 $_REQUEST取值为空
默认的 $_REQUEST 会获取 $_POST, $_GET, $_COOKIE的数据,这些可以通过查看 php.ini来确认: 由上图可以看出,获取的内容是通过 variables_order 和 ...
- Mysql的select in会自动过滤重复的数据
默认使用 SELECT 语句: 当加上in范围后,结果如下图: in范围内的数据,如果有重复的,只会选择第一个数据. 所以如果不是直接使用SQL语句来查询,而是在代码中来查询时,记得使用 distin ...
- C++函数中返回引用和返回值的区别
一.主要讨论下面两个函数的区别: int& at() { return m_data_; } int at() { return m_data_; } 上面两个函数,第一个返回值是int的引用 ...
- Geohash距离估算
http://www.cnblogs.com/LBSer/p/3298057.html 一.经纬度距离换算 a)在纬度相等的情况下: 经度每隔0.00001度,距离相差约1米: 每隔0.0001度,距 ...
- MVVM框架在unity开发中的使用
1.什么是MVVM 借用一下百度百科上对MVVM的介绍,MVVM是Model-View-ViewModel的简写,它本质上就是MVC 的改进版.MVVM 就是将其中的View 的状态和行为抽象化,让我 ...
- IDEA破解教程(破解到2100年)的注意事项
https://blog.csdn.net/yl1712725180/article/details/80309862 1.上边是教程 2.注意事项,在两个文件中加 -javaagent:加上你j ...