谨慎使用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驱 ...
随机推荐
- PHP之高性能I/O框架:Libevent(二)
Event扩展 Event可以认为是替代libevent最好的扩展,因为libevent已经很久不更新了,而Event一直在更新,而且Event支持更多特性,使用起来也比libevent简单. Eve ...
- centos7 安装配置zookeeper
https://blog.csdn.net/AaronLin6/article/details/78438877 https://www.cnblogs.com/sxdcgaq8080/p/74924 ...
- SQL分区表示例
-- Create tablecreate table TT_FVP_OCR_ADDRESS( id NUMBER not null, waybill_no VARCHAR2(32) not null ...
- FFmpeg在JAVA中的使用-音频提取&字幕压缩
由于项目需求中涉及到视频中音频提取,以及字幕压缩的功能,一直在研究ffmpeg,仅仅两个功能,却深受ffmpeg的折磨. 今天谈谈ffmpeg在java中的简单使用,首先下载FFmpeg包,官方地址: ...
- 【转载】图片 CSS:怎样才能 “响应式 + 固定宽高比例”?
自己根据项目需要,把代码摘了出来 <div class="img-box"></div> .img-box{ height:0; padding-botto ...
- LINUX 下Jexus部署ASP.NET Core WebApi
服务器:LINUX ubuntu16.04 开发软件:VS2015 Update3 dotnet sdk: DotNetCore.1.0.0-VS2015Tools.Preview2 1. ...
- C# Thread.Abort方法真的让线程停止了吗?
大家都知道在C#里面,我们可以使用 Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Threa ...
- Scott用户的表结构
在Oracle的学习之中,重点使用的是SQL语句,而所有的SQL语句都要在scott用户下完成,这个用户下一共有四张表,可以使用: SELECT * FROM tab; 查看所有的数据表的名称,如果现 ...
- Computer - 在VM7虚拟机中使用主机打印机
在VM7虚拟机中使用主机打印机 在VMware Workstation 7中提供了一项新的功能:虚拟机可以直接使用主机的打印机.在以前的版本中,如果想在虚拟机中使用主机的打印机,一般是在主机创建“打印 ...
- Java基础——6种常用类讲解
本文主要介绍几种Java中常用类的应用. 一.System类 从API当中我们可以看出,public final class System exends Object.System类包含一些有用的字段 ...