谨慎使用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 -- 表单多选
----- 011-form.html ----- <!DOCTYPE html> <html> <head> <meta http-equiv=" ...
- Jquery初体验一
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- SHELL脚本编程的常识和VI常用技巧
来源:http://mprc.pku.edu.cn/mentors/training/TrainingCourses/material/ShellProgramming.HTM#_Toc3751808 ...
- js便签笔记(12)——浏览TOM大叔博客的学习笔记 part2
1. 前言 昨天写了<js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1>,简单记录了几个问题.part1的重点还是在于最后那个循环创建函数的问题,也就是多个子函数公用一个闭 ...
- mac 安装 python mysqlclient 遇到的问题及解决方法
在 mac 上安装 mysqlclient 遇到了一些问题,查找资料很多人都遇到了同样的问题.通过资料和试验,成功了.这里记录一下,希望帮到遇到同样问题的人. 本人使用python3, 安装步骤如下: ...
- nginx-access.log的logstash解析
1.nginx的access的格式: log_format hehe '$http_host $server_addr $remote_addr [$time_local] "$reques ...
- Docker 入门 之基本命令
3 Docker 入门 首先确保docker 已成功安装在Linux 或windows 系统中 我们可以使用 docker info 查看docker是否成功安装和正常运行 运行我们第一个docker ...
- 在Java8的foreach()中不能break,如果需要continue时,可以使用return
今天使用lambda表达式处理集合时,发现对return.break以及continue的使用有点迷惑,于是自己动手测试了一下,才发现在使用foreach()处理集合时不能使用break和contin ...
- 网页中通过js修改img的src属性刷新图片时,图片缓存问题现象表述及问题解决【ps:引用大神案例http://blog.csdn.net/goodleiwei/article/details/50737548】
问题:上传一张图片,通过js更新src属性刷新图片使其即时显示时, 当img的src当前的url与上次地址无变化时(只更改图片,名称不变,不同图片名称相同)图片不变化(仍显示原来的图片) 但通过fir ...
- SQl常用语句总结(持续更新……)
创建示例数据库 USE master; GO IF DB_ID (N'mytest') IS NOT NULL DROP DATABASE mytest; GO CREATE DATABASE myt ...



