您当前位于: 首页 » 我爱PHP, 系统架构设计 » 一个单引号引发的MYSQL性能损失

一个单引号引发的MYSQL性能损失12/22/2010

生活中难免遇到一些不如意,有些来自我们自身,而有些不是。今天冬至,说这一天是北半球白天最短、黑夜最长的。今天我们来分享下我的一个同事提到加没加单引号的巨大区别,对于MYSQL性能优化很有意义。

刚刚我们说过了,生活中难免会有一些不如意,比如,我们用一个字符串类型的字段来作为主键,表面上,这太不如意了,然而,事实也证明这是有用的。问题也就出来了,当在查询语句中对该字段值加上单引号和不加查询耗时相差百倍!

我建立的测试表是这样子的:

CREATE TABLE `foo` (
  `key` VARCHAR(10) NOT NULL,
  `time` INT(11) NOT NULL,
  PRIMARY KEY (`key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

然后插入30多万条数据,然后执行下面的SQL语句:

SELECT *
FROM `foo`
WHERE `key` =1293322797

查询花费 0.1288 秒,大约花费这么久的时间,然后,给1293322797加上单引号:

SELECT *
FROM `foo`
WHERE `key` ='1293322797'

查询花费 0.0009 秒,基本上相差100倍!!!也就是说不加单引号MYSQL性能损失了100倍,很震撼的比例!

后来用EXPLAIN分别跑了一下上面两条语句,见下面两张图:


没有单引号时


有单引号时

很明显,不使用单引号没有用上主索引,并进行了全表扫描,使用单引号就能使用上索引了。
后来我用大于分别进行了测试,返回的结果集相同,而他们的耗时和上面一样,用EXPLAIN测试,也和上面一样

SELECT *
FROM `foo`
WHERE `key` >1293322797
SELECT *
FROM `foo`
WHERE `key` >'1293322797'

加单引号和不加单引号就是这么大的差别!就是会对mysql性能产生这么大的影响。
再后来,我将字段`key`换成INT类型,这时候,加不加单引号,就没有什么差别了,EXPLAIN显示他们都同样能够用上主索引,只是key_len变短了。

就是这些,综上所述,我们在写SQL查询的时候还是不厌其烦的加上单引号吧,似乎那没有坏处。谢谢收看,接下来播放一条本台刚刚收到的消息:“我要下楼去买点汤圆,以庆贺冬至!”

| 35条评论 标签:  

35条评论
  1. 胖子说道:

    这个时候可以问下为什么是这样?
    另外,昨天吃了饺子 and 汤圆

  2. 红酒网说道:

    初次到这博客来,知识还是挺丰富的

  3. suyuwen1说道:

    高 高 高

  4. felixceo说道:

    要多注意 第一次搜索和第二次搜索的差别 期间是有缓存的
    你试着把两句倒过来看看

  5. pAUL gAO说道:

    字段类型是 varchar,你用数值当条件,肯定会导致类型转换的。

  6. felixceo说道:

    我这边测试不会这样子 可能是mysql版本问题?
    测试过phpmyadmin中和cli模式下 以及把10W的数据从innodb转向myisam 效果和你不一样
    同样用的是主键以及测试了索引 在20W的数据中
    最终结果两则无差别

  7. mytuan说道:

    这不mysql的问题,是语句本身的问题,你用数字查当然慢了 ,你放oracle上也一样慢。

  8. 发仔说道:

    兄弟,你说的加单引号,不是快了吗?应该说,加单引号节省了资源消耗?
    而你在文章里“查询花费 0.0009 秒,基本上相差100倍!!!也就是MYSQL性能损失了100倍,很震撼的比例!”
    是表达有误?

  9. new zender说道:

    我有个疑问,这上面的例子都是先用无单引号,再加上单引号来做的测试,
    如果反过来会是什么结果,会不会是因为第一次用无单引号的查询,查询结果已经缓存到内存,而第二次有单引号查询时,查询直接从缓存中读取而节省了时间呢?

  10. 流浪汉说道:

    受教了。。。。。。。。

  11. 旋木说道:

    嗯。这个问题,确实是要注意。
    我以前以为int型的字段可以不用加引号,会更快的。可是有一天,我发现,如果没有加上引号,会查询出多条数据,而加上了引号,则只出现一条。不明所以,但是,现在都果断的加上了单引号。

  12. jam说道:

    目前我数据库大约有3KW数据、也没出现你说的这种情况。主键一般是整型。不加引号不更好?

  13. cevin说道:

    如果key是int型就不会了吧。

  14. jasen说道:

    使用varchar作主键本身就是蛋疼,这种比较没有使用价值.

  15. […] 例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。关于这一点可以围观:一个单引号引发的MYSQL性能损失。 […]

  16. nesc说道:

    数据库编程,每个符号都显得特别重要

  17. 韩俊说道:

    这个不只是作为主键会产生问题,作为其他索引键也会有类似问题。
    int型索引字段,查询时加”,不会导致查询时不使用索引,
    而字符换类型字段,查询不加”,却会导致查询时不适用索引,
    而且还有一点是如果没有这个单引号,Innodb的存储引擎表的查询都会因为无索引可以,而上升为表级锁定

  18. Magento说道:

    最保险的写法是,数据类型完全匹配。

  19. mohock说道:

    大家往往都会疏忽的MYSQL标准语句写法~~

  20. huangjin说道:

    恩 应该是类型转换引起的; 第2个用< mysql会自动帮你指定索引,所以需要自己再强制指定下索引

发表评论