首先看案例:

表中字段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. kuangbin专题十二 HDU1069 Monkey and Banana (dp)

    Monkey and Banana Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  2. Linux系统之ssh命令

    ssh命令用于远程登录上Linux主机. 常用格式:ssh [-l login_name] [-p port] [user@]hostname更详细的可以用ssh -h查看. 不指定用户: ssh 1 ...

  3. 【Cracking the Code Interview(5th edition)】一、数组与字符串(C++)

    1.1 实现一个算法,确定一个字符串的所有字符是否全都不同.不允许使用额外的数据结构. 解答:这里假定字符集为ASCII码,可以与面试官沟通确认字符串使用的字符集.由于字符集是有限的,建立一个数组模拟 ...

  4. Mybatis学习笔记(七) —— 关联查询

    一.一对多查询 需求:查询所有订单信息,关联查询下单用户信息. 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询.如果从用户信息出发查询用户下的订单信息则 ...

  5. Kibana 视图开发入门参考文档

    官方教程:https://www.elastic.co/blog/developing-new-kibana-visualizations GitHub源码:https://github.com/el ...

  6. 毕业设计 python opencv实现车牌识别 颜色定位

    主要代码参考https://blog.csdn.net/wzh191920/article/details/79589506 GitHub:https://github.com/yinghualuow ...

  7. Helvetic Coding Contest 2016 online mirror A1

    Description Tonight is brain dinner night and all zombies will gather together to scarf down some de ...

  8. BeautifulSoup4模块的使用

    1. 安装 pip3 install beautifulsoup42. 使用 from bs4 import BeautifulSoup obj = BeautifulSoup("HTML内 ...

  9. spring aop实现log 日志跟踪

    之前写的那篇是基于springboot的(https://www.cnblogs.com/yaoyuan2/p/10302802.html),由于遗留项目用的是spring,因此需要在spring基础 ...

  10. Java学习笔记day04_数组

    1.switch case switch语句中表达式的数据类型是有要求的: JDK 1.0 ~ 1.4 , 数据类型接受byte, short, int, char JDK 1.5 , 数据类型接受b ...