首先看案例:

表中字段FPHONE_IMEI是varchar类型的,主键也建立在FPHONE_IMEI 字段上,原则上只要where条件中用到了这个字段,就会走索引,这也是建立索引的目的,可事实是这样子么。首先看下面这条查询,初看,唯一值查询走索引应该很快,实际上呢,从执行计划可以看出,没有使用到索引,而是全表扫描,所有这条查询语句性能好不到哪里。

看看实际的执行时间:

1.11s,超过一秒了我们定义为慢SQL,因此这条语句是有性能问题的。

再看下面这条查询语句,就和预想的一样,走主键索引,查询很快,也是我们希望看到的结果。

看看执行时间:

0.01s,这个时间才是我们需要的。

从写法上来看,上述两条语句差不多,为何性能有如此大的差距呢,问题就在差不多上面,注意看仔细咯,看第一条语句,where条件中给定的值没有引号,而FPHONE_IMEI 字段是字符串的,也就是两边类型不匹配,第二条语句类型是匹配的,因此没有性能问题,所以导致上述差异的原因是类型不匹配。那问题来了:

1.为何类型不匹配会导致性能如何大差异呢

2.是不是类型不匹配就一定会导致性能问题呢。

请看下文:

mysql在做比较时,如果发现类型不匹配,会发生自动隐式类型转换,是的,mysql是会自动隐式类型转换,既然是转换,那转换的规则是怎样的,规则如下:

1.如果一个或两个参数都是空的,比较的结果为null。null与null比较,结果为null,无需进行转换。

2.如果两个比较的两个参数都是string,按string比较,不做类型转换。

3.如果两个比较的两个参数都是integer,按integer比较,不做类型转换。

4.十六进制的值和非数字做比较时,会被当做二进制串来比较。

5.有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp。

6.有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较

7.所有其他情况下,两个参数都会被转换为浮点数再进行比较。

说完转换的规则,再说下索引,索引的作用是为了让mysql根据查询条件快速定位到相应的记录,从而减少IO次数,达到快速返回结果的目的。但是如果mysql发现查询条件无法满足快速定位到记录的时候,会放弃索引,而走全表扫描,因为它觉得全表扫描比走索引更优,当然这一系列操作都是mysql优化器决定。

再接着上面的两条SQL语句说,从上述的规则来看,第一条SQL符合第七条规则,因此都需要转换为浮点数再进行比较。那就看看mysql对具体的数值是如何进行转换的:

我们可以看到,一个float数值可以由多个字符串转换而来,比如上面的1,发生转换的可以有 1,'1','1xxx','  1',对于’1xxx’这样的,会发生截断,非数字会丢弃。因此如果一个索引建立在string类型上,如果这个字段和一个int类型的值比较,这时两者同样是转换为float,但是因为索引是string的,而string转换为同一个float的情况很多,同一个float值对应的string可能有很多,这就有点类似%string%的情况,mysql认为这种情况无法通过访问索引来快速的定位记录,索引的效果是访问少而准,从而索引失效,进而走全表扫描,既然是全表扫描,这个性能是好不到哪里去的,这也是第一条语句出现的问题,字符串隐式转换为float类型,从而导致索引失效,第一条语句出现的warnings而正是因为发生了隐式转换导致字段截断而出现的,这也证实了隐式转换的发生。而对于两边都是string的话,不发生类型转换,而是直接比较,从而可以通过走索引进行快速查询。

反过来又会怎样呢,另外一种情况,当一个索引建立在int类型上,如果这个字段和一个字符串比较,会是怎么样的情况呢,同样会发生类型转换,两边都转换为float类型,但是int类型转换到float是唯一的,不会像上面情况一样,不会存在可能很多记录转换为同一个值的情况,同时字符串转换为唯一的int类型值,因此是可以用到索引定位到具体记录的(如果记录存在),从而可以达到走索引的效果,快速响应查询。看下面例子进一步说明:

表中x字段是int类型,建立有索引,

第一条查询语句,都是int类型比较,和预想一样,走索引。

第二条查询语句,和纯数字字符串比较,和我们上面说的转换第二种情况一样,同样走索引。

第三条查询语句,和混合字符串比较,同样我们上面说的转换第二种情况一样,同样走索引,只是字符串发生了截断。

上述这个例子和我们说的第二种情况一致,发生类型转换还是走索引。

我们再回到最前面提出的问题:

1.       为何类型不匹配会导致性能如何大差异

2.       是不是类型不匹配就一定会导致性能问题

相信上面的解读已经很好的回答了这两个问题。对1问题,类型不匹配,会导致发生隐式类型转换,根据转换的结果可能导致性能影响。对2问题,并不是发生类型转换就一定导致性能问题,这个要看具体转换的字段,所以也不是一定的。但是我们在拼写SQL语句的时候,不能只看到不一定,而是要做到一定不要,不要将类型不匹配的字段进行比较,要保证WHRER条件里的数据类型必须和字段数据类型一致。

总结: where查询条件中,务必保证提供的数据类型和表中字段类型一致,而不是让mysql发生隐式类型转换,隐式转换不一定按我们预想的来转换,在一些转换条件下会产生性能影响,而且往往这种情况下性能问题比较难以发现和定位

引用自:http://blog.itpub.net/22418990/viewspace-1302080/

WHRER条件里的数据类型必须和字段数据类型一致的更多相关文章

  1. 【转】MySQL数据类型和常用字段属性总结

    来源:http://www.jb51.net/article/55853.htm 这里先总结数据类型.MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. ...

  2. MySQL数据类型和常用字段属性总结

    前言 好比C++中,定义int类型需要多少字节,定义double类型需要多少字节一样,MySQL对表每个列中的数据也会实行严格控制,这是数据驱动应用程序成功的关键.MySQL提供了一组可以赋给表中各个 ...

  3. 批量替换数据库中所有用户数据表中字段数据类型为char和varchar到nvarchar的脚本

    解决问题:字段类型为char的总是占用指定字节长度(末尾好多空白符号),varchar数据类型长度一个汉字占2个字节,内容存储为中文的字段个人建议全部使用nvarchar. 操作说明:打开SQL Se ...

  4. SPSS数据类型:测量字段、角色字段

    一:测量字段 • 默认值.具有未知存储类型和值的数据(例如,由于其尚未被读取)将显示为<默认值>. •  连续.用于描述整数.实数或日期/时间等数字值,如范围 0 - 100 或 0.75 ...

  5. SQL数据库字段数据类型详细说明

    这里先总结数据类型.MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. 日期和时间数据类型 MySQL数据类型 含义 date 3字节,日期,格式:20 ...

  6. 二 sql语句,常用字段数据类型

    MySQL中常用DDL命令   database definition language  与 DML命令 :  database definition language 操作数据库: 创建数据库 : ...

  7. MySQL字段数据类型表

    * MySQL支持所有标准SQL数值数据类型. 数值类型BIT数据类型保存位字段值,并且支持MyISAM.MEMORY.InnoDB和BDB表.作为SQL标准的扩展,MySQL也支持整数类型TINYI ...

  8. if条件里比较浮点数

    晚上看会儿书,基础的东西,很多都不熟练,不得不佩服那些人真的很厉害,为啥会想到那些,我这傻脑袋是想不到,暂时...... 比较3.3333与3 #!/bin/bash var1=`echo " ...

  9. Oracle_字段数据类型

    Oracle_字段数据类型 数据库表字段的数据类型 字符数据类型 CHAR:存储固定长度的字符串 VARCHAR2 :存储可变长度的字符串 数值数据类型 NUMBER:存储整数和浮点数,格式为NUMB ...

随机推荐

  1. charset=iso-8859-1

    今天群里有人在问, 求解:charset="ISO-8859-1"是什么意思 其实我也不大懂,然后就去翻阅了下资料.科普开始: 网页制作中遇到的编码,乱码问题之一:charset= ...

  2. 利用Android studio开发Java工程

    1. 新建项目 新建项目肯定是去new,但到底是new project还是new module是一个问题.在这解释一下,如果new project的话是新建一个工程,相当于新建一个工作区,工程中可以有 ...

  3. python 批量修改包名

    #coding=utf-8 import os #import re # 设置编码为utf-8 否则会报错..这时候 sublime控制台会报乱码.但是别担心,utf-8 文件 并不会报错 impor ...

  4. SSH防入侵

    1.1 ssh防止入侵方法说明 如何防止SSH登录入侵小结: 1.用密钥登录,不用密码登陆 2.牤牛阵法:解决SSH安全问题 a.防火墙封闭SSH,指定源IP限制(局域网.信任公网) b.开启SSH只 ...

  5. Sublime Text 3 3126 安装+注册码

    首先,到官网下载且安装,个人是安装版本的 https://www.sublimetext.com/3 接着,写入注册码.2016/11/26 亲测有效 —– BEGIN LICENSE —– Mich ...

  6. 5.SpringMVC

    1.SpringMVC概述 概述: SpringMVC是基于请求驱动,围绕一个核心Servlet 转发请求到对应的Controller而设计的优点:是一个典型的教科书式的MVC构架,易学易用提供了清晰 ...

  7. windows服务开启(收藏url)

    windows服务开启(收藏url) http://blog.csdn.net/wanda39kela/article/details/46310093

  8. sf01_什么是数据结构

    数据结构解决什么问题 如何在计算机中存储数据和信息,采用什么样的方法和技巧加工处理这些数据,都是数据结构需要努力解决的问题. 解决问题的步骤 使用计算机解决问题的步骤:分析具体问题得到数学模型,设计解 ...

  9. 跨域的问题(jsonp和cors)

    由于浏览器的同源策略,用户想要跨域访问浏览器就会报错,那么就涉及到解决跨域的问题.最近我接触到的解决方法是两个,jsonp和cors. jsonp(json with padding)我们虽然不能直接 ...

  10. cookie 跨域访问

    废话不知道该说些什么...先看代码吧. cookie 是浏览器保存在用户计算机上的少量数据 //读取cookie function getCookie(name) { var arr, reg = n ...