文档详情

MySQL的in查询不走索引?我拿什么拯救你!.doc

发布:2024-10-13约1.84千字共4页下载文档
文本预览下载声明

PAGE

PAGE1

MySQL的in查询不走索引?我拿什么拯救你!

为什么写这篇文章呢?因为我不想让大家在错误下去!

昨天CSDN正在进行一个2018年的博客之星活动,入围了200名的博客专家!大家正在讨论说2018年博客之星页面有bug的问题时,有一位网友发了一张图片,一条SQL查询有问题。于是下面就有几个回答说MySQL查询in是不走索引的!

哇,我惊呆了。这种话都出来了!我想证明我是错的,于是我到网上搜索了非常多的文章,什么MySQL优化实战,MySQL军规36条,30条SQL优化军规,SQL语句优化原则,mysql语句优化建议,数据库查询优化方法总结等等有非常多的文章在描述,MySQL中in查询不走索引。

这些文章当中有些是2018年才发出来的,完全属于误导读者。今天我们一起来看看MySQL的in查询到底走不走索引?

首先说一下,我的测试环境:

MySQL版本:SELECTVERSION();mdash;5.6.28-cdb2016-log

存储引擎:innodb

一些基本配置,我就不贴了,对于我们这个问题影响的不大。

使用descxttblog;名称查看一下表结构。我就不贴图了,直接给大家贴上建表语句。

然后循环插入100万条测试数据。

首先我们看一下无索引的情况,xttblog表中的name值已经非常的散了。查询时间0.55秒左右。

我们在查一下xttblog表中的statusin的情况,耗时17秒左右。

通过EXPLAIN对上面两条查询语句进行分析(不懂EXPLAIN的可以看我的这篇文章《拜托别在问我MySQL性能优化了!》),它们都没有走索引。name的值因为更分散,查询速度更快。

再来看看有索引的情况下,in的执行效率。

我们的主键id是一个索引,上面语句的查询耗时0.02秒左右。

为了比较,我们再给xttblog表的name字段加上索引。

然后执行下面的查询:

当name字段添加了索引后,in查询耗时0.02毫秒左右。

EXPLAIN分析发现它们的type都是range,表示使用索引范围查询,通过索引字段范围获取表中部分数据记录.这个类型通常出现在=,lt;,,=,lt;,lt;=,ISNULL,

虽然Extra的值是Usingwhere,它表示优化器需要通过索引回表查询数据。使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。Extra列出现Usingwhere表示MySQL服务器将存储引擎返回服务层以后再应用WHERE条件过滤。

现在来看,在回答题目中的问题。MySQL的in查询在5.5以上的版本中存储引擎都是innodb的,正常情况下会走索引的!至于MyISAM的情况大家自己去研究,或者我以后抽时间了来写!

如果是5.5之前的版本确实不会走索引的,在5.5之后的版本,MySQL做了优化。MySQL在2010年发布5.5版本中,优化器对in操作符可以自动完成优化,针对建立了索引的列可以使用索引,没有索引的列还是会走全表扫描。

比如,5.5之前的版本(以下都是5.5以前的版本)。select*fromawhereidin(selectidfromb);这条sql语句它的执行计划其实并不是先查询出b表的所有id,然后再与a表的id进行比较。mysql会把in子查询转换成exists相关子查询,所以它实际等同于这条sql语句:select*fromawhereexists(select*frombwhereb.id=a.id);

而exists相关子查询的执行原理是:循环取出a表的每一条记录与b表进行比较,比较的条件是a.id=b.id。看a表的每条记录的id是否在b表存在,如果存在就行返回a表的这条记录。

关于exists的问题,我们以后抽时间再说。

互联网上的信息太过广泛,但这不应该成为我们掉以轻心的借口,抱着存疑求是的精神进行甄别,任何信息只有在我们实践验证后方可全信,用在生产开发上的知识,不容有失!

尽信书,不如无书!

显示全部
相似文档