WHRER条件里的数据类型必须和字段数据类型一致
首先看案例:
表中字段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条件里的数据类型必须和字段数据类型一致的更多相关文章
- 【转】MySQL数据类型和常用字段属性总结
来源:http://www.jb51.net/article/55853.htm 这里先总结数据类型.MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. ...
- MySQL数据类型和常用字段属性总结
前言 好比C++中,定义int类型需要多少字节,定义double类型需要多少字节一样,MySQL对表每个列中的数据也会实行严格控制,这是数据驱动应用程序成功的关键.MySQL提供了一组可以赋给表中各个 ...
- 批量替换数据库中所有用户数据表中字段数据类型为char和varchar到nvarchar的脚本
解决问题:字段类型为char的总是占用指定字节长度(末尾好多空白符号),varchar数据类型长度一个汉字占2个字节,内容存储为中文的字段个人建议全部使用nvarchar. 操作说明:打开SQL Se ...
- SPSS数据类型:测量字段、角色字段
一:测量字段 • 默认值.具有未知存储类型和值的数据(例如,由于其尚未被读取)将显示为<默认值>. • 连续.用于描述整数.实数或日期/时间等数字值,如范围 0 - 100 或 0.75 ...
- SQL数据库字段数据类型详细说明
这里先总结数据类型.MySQL中的数据类型大的方面来分,可以分为:日期和时间.数值,以及字符串.下面就分开来进行总结. 日期和时间数据类型 MySQL数据类型 含义 date 3字节,日期,格式:20 ...
- 二 sql语句,常用字段数据类型
MySQL中常用DDL命令 database definition language 与 DML命令 : database definition language 操作数据库: 创建数据库 : ...
- MySQL字段数据类型表
* MySQL支持所有标准SQL数值数据类型. 数值类型BIT数据类型保存位字段值,并且支持MyISAM.MEMORY.InnoDB和BDB表.作为SQL标准的扩展,MySQL也支持整数类型TINYI ...
- if条件里比较浮点数
晚上看会儿书,基础的东西,很多都不熟练,不得不佩服那些人真的很厉害,为啥会想到那些,我这傻脑袋是想不到,暂时...... 比较3.3333与3 #!/bin/bash var1=`echo " ...
- Oracle_字段数据类型
Oracle_字段数据类型 数据库表字段的数据类型 字符数据类型 CHAR:存储固定长度的字符串 VARCHAR2 :存储可变长度的字符串 数值数据类型 NUMBER:存储整数和浮点数,格式为NUMB ...
随机推荐
- [ZJOI2008]生日聚会 BZOJ1037 dp
题目描述 今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party. hidadz带着朋友们来到花园中,打算坐成一排玩游戏.为了游戏不至于无聊,就座的方案应满足如下条件: 对于任意连续 ...
- PHP 实现实现多线程
前言 前些天帮同事查一个问题,第一次接触到了 PHP 的多线程,原以为 PHP 普遍都是单线程模型,并不适合多线程领域,花些时间翻了几个多线程的项目源码之后,发现 PHP 的多线程也颇有可取之处,活用 ...
- 【记录一下】从0到1 我的python开发之路
请设计实现一个商城系统,商城主要提供两个功能:商品管理.会员管理. 商品管理: - 查看商品列表 - 根据关键字搜索指定商品 - 录入商品 会员管理:[无需开发,如选择则提示此功能不可用,正在开发中, ...
- Bootstrap中的Glyphicon 字体图标
在Bootstrap框架中也为大家提供了近200个不同的icon图片,而这些图标都是使用CSS3的@font-face属性配合字体来实现的icon效果. 1 <!DOCTYPE html> ...
- Python集合字典运算符
1.集合2.字典3.运算符优先级 1.集合 创建:{} set([]) 注意:创建空的集合要用set() 特点:元素唯一,无序 运算: & 交集 | 并集 - 差集 方法: s ...
- js 返回 差 集
//接受两个数组,返回差集 function getDiffSet(a,b){ a.sort(charSort); b.sort(charSort); if(a.length>=b.length ...
- sublime中正则替换
匹配 <header></header> , “.” 是匹配任意 非 换行 符号 而 \s\S 匹配任何符号 匹配div class为navbar 的 div <d ...
- 爬取猫眼电影top100的代码
废话不说,代码附上: #encoding:utf-8 import requests import re import json from multiprocessing import Pool #多 ...
- Go语言基础之2--字符串详解
一.字符串原理解析 1. 字符串底层就是一个byte数组,所以可以和[]byte类型互相转换:(字符串可以存文本,也可以存二进制,因为其本来就是一个字节流) 2. 字符串之中的字符是不能修改的,那怎 ...
- oracle Clob类型转换成String类型
转载:https://www.cnblogs.com/itmyhome/p/4131339.html Clob类型转换成String类型 oracle中表结构如下: create table GRID ...