之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢?

test_1的表结构:

CREATE TABLE `test_1` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`user_id` varchar(30) NOT NULL,

`name` varchar(30) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `idx_user_id` (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

查看执行计划,可以看出进行了全表扫描,并没有用上user_id的索引。

mysql> explain select * from test_1 where user_id=1;

+----+-------------+--------+------+---------------+------+---------+------+------+-------------+

| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows | Extra       |

+----+-------------+--------+------+---------------+------+---------+------+------+-------------+

|  1 | SIMPLE      | test_1 | ALL  | idx_user_id   | NULL | NULL    | NULL |    3 | Using where |

+----+-------------+--------+------+---------------+------+---------+------+------+-------------+

1 row in set (0.01 sec)

仔细看下表结构,user_id的字段类型:  `user_id` varchar(30) NOT NULL,

而用户传入的是int,这里会有一个隐式转换的问题。隐式转换会导致全表扫描。

把输入改成字符串类型,执行计划如下,这样就会很快了。

mysql> explain select * from test_1 where user_id='1';

+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+

| id | select_type | table  | type | possible_keys | key         | key_len | ref   | rows | Extra       |

+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+

|  1 | SIMPLE      | test_1 | ref  | idx_user_id   | idx_user_id | 92      | const |    1 | Using where |

+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------------+

1 row in set (0.00 sec)

此外,还需要注意的是:

数字类型的0001等价于1

字符串的0001和1不等价

mysql> select * from test_1;

+----+---------+------+

| id | user_id | name |

+----+---------+------+

|  1 | 0001    | kate |

|  2 | 1101    | Jim  |

|  3 | 1       | Jim  |

+----+---------+------+

3 rows in set (0.01 sec)

mysql> select * from test_1 where user_id=1;

+----+---------+------+

| id | user_id | name |

+----+---------+------+

|  1 | 0001    | kate |

|  3 | 1       | Jim  |

+----+---------+------+

2 rows in set (0.00 sec)

mysql> select * from test_1 where user_id='1';

+----+---------+------+

| id | user_id | name |

+----+---------+------+

|  3 | 1       | Jim  |

+----+---------+------+

1 row in set (0.00 sec)

如果表定义的是int字段,传入的是字符串,则不会发生隐式转换。

看下面的测试:

CREATE TABLE `test_2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

mysql> explain select * from test_2 where user_id=1;
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
| 1 | SIMPLE | test_2 | ref | idx_user_id | idx_user_id | 4 | const | 2 | |
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
1 row in set (0.00 sec)

mysql> explain select * from test_2 where user_id='1';
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
| 1 | SIMPLE | test_2 | ref | idx_user_id | idx_user_id | 4 | const | 2 | |
+----+-------------+--------+------+---------------+-------------+---------+-------+------+-------+
1 row in set (0.00 sec)

MySQL SQL优化之字符串索引隐式转换的更多相关文章

  1. SQL Server中提前找到隐式转换提升性能的办法

        http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...

  2. 【转】SQL SERVER标量表达式的隐式转换

    在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...

  3. SQL Server有意思的数据类型隐式转换问题

    写这篇文章的时候,还真不知道如何取名,也不知道这个该如何将其归类.这个是同事遇到的一个案例,案例比较复杂,这里抽丝剥茧,仅仅构造一个简单的案例来展现一下这个问题.我们先构造测试数据,如下所示: CRE ...

  4. mysql字符串的隐式转换导致查询异常

    如果mysql某个字段(name)类型为varchar, 加了索引,在执行where查询的时候,传入了int的值,这样就会全表扫描,把每一条的值都转换成int(会出现"中国"-&g ...

  5. MySQL性能优化:MySQL中的隐式转换造成的索引失效

    数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很 ...

  6. JavaScript 隐式转换

    javascript 中的怪癖,js运算符隐式类型转换 x + "" //等价于 String(x) + x //等价于 Number(x),也可以写成x-0 !!x //等价于 ...

  7. ORACLE数据库中执行计划出现INTERNAL_FUNCTION一定是隐式转换吗?

    ORACLE数据库中,我们会使用一些SQL语句找出存在隐式转换的问题SQL,其中网上流传的一个SQL语句如下,查询V$SQL_PLAN的字段FILTER_PREDICATES中是否存在INTERNAL ...

  8. 每天多一点(2016.12.04)》Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

  9. Javascript隐式转换

    乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...

随机推荐

  1. iOS实例下载:使用腾讯的SDK将新浪微薄嵌入到应用中

    最近在做应用中添加SNS分享功能,只需要分享功能,腾讯的SDK和Demo还是挺直观的,看了下基本上就能用了,而新浪的Oauth认证看了个例子是跳出程序到Web上去认证的,体验很不好.不过Oauth认证 ...

  2. 【tyvj1860】后缀数组

    描述 我们定义一个字符串的后缀suffix(i)表示从s[i]到s[length(s)]这段子串.后缀数组(Suffix array)SA[i]中存放着一个排列,满足suffix(sa[i])< ...

  3. 【BZOJ2152】聪聪可可

    Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...

  4. ubuntu系统使用快捷键打开终端方式总结

    ctrl + alt + T 三键齐下打开虚拟终端 ctrl + alt + F1 (~F6)打开系统终端ctrl + alt + F7 返回图形界面都可以使用exit命令关闭, 不同的是虚拟终端ex ...

  5. ajax加php实现三级联动

    js代码 <script type="text/javascript">    function get_next(t,pid){  //当前元素的id,当前optio ...

  6. POJ 1269 Intersecting Lines(几何)

    题目链接 题意 : 给你两条线段的起点和终点,一共四个点,让你求交点坐标,如果这四个点是共线的,输出“LINE”,如果是平行的就输出“NONE”. 思路 : 照着ZN留下的模板果然好用,直接套上模板了 ...

  7. 【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)

    2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上 ...

  8. 多线程(一)NSThread

    iOS中多线程的实现方案: 技术 语言 线程生命周期 使用频率 pthread C 程序员自行管理 几乎不用 NSthread OC 程序员自行管理 偶尔使用 GCD C 自动管理 经常使用 NSOp ...

  9. 【mysql的设计与优化专题(5)】慢查询详解

    查询mysql的操作信息 show status -- 显示全部mysql操作信息 show status like "com_insert%"; -- 获得mysql的插入次数; ...

  10. ANDROID_MARS学习笔记_S01_012_SeekBar

    1.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns: ...