MySQL explain结果Extra中”Using Index”与”Using where; Using index”区别探究

问题背景

最近用explain命令分析查询sql执行计划,时而能看到Extra中显示为”Using index”或者”Using where; Using Index”,对这两者之间的明确区别产生了一些疑惑,于是通过网上搜索、自行实验探究了一番其具体区别。

测试数据准备

以下表作为测试表进行sql分析。

CREATE TABLE test_table (
  id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  f0 int(11) NOT NULL,
  f1 varchar(50) NOT NULL,
  f2 int(11) NOT NULL,
  PRIMARY KEY (id),
  KEY idx_f0_f1 (f0,f1)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4

包含以下数据:

INSERT INTO test_table (f0, f1, f2) VALUES (1, '111', 1), (2, '222', 2), (3, '333', 3), (4, '444', 4), (5, '555', 5), (6, '666', 6);

仅有Using where含义

对于仅有Using where的情况,文档中写到:

A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index.

第一句话的大意是有一个where子句用于限制返回哪些匹配行到客户端或者下一个表–简单说就是有使用where条件限制要返回的select结果,从这里并没有提出Using where与是否需要回表读完整行数据有任何联系。
如下语句无where条件所以无Using where:

 EXPLAIN SELECT * FROM test_table;
 +----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | test_table | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------+

如下语句使用where子句添加限制,其Extra中有Using where结果:

EXPLAIN SELECT * FROM test_table WHERE f2=3;
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test_table | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |    16.67 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+------+----------+-------------+

仅有Using index含义

仅有Using index的情况,文档中写道:

The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.

即表示where 和select中需要的字段都能够直接通过一个索引字段获取,无需再实际回表查询,当查询涉及的列都是某一单独索引的组成部分时即为此种情况,这实际上就是索引类型中覆盖索引。
如下语句所有查询列均包含在索引中,所以有Using index:

EXPLAIN SELECT f0, f1 FROM test_table WHERE f0=3;
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
| id | select_type | table      | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra       |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | test_table | NULL       | ref  | idx_f0_f1     | idx_f0_f1 | 4       | const |    1 |   100.00 | Using index |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------------+

如下语句虽然where子句涉及列均包含在索引中,但是select中包含额外列,所以无Using index:

EXPLAIN SELECT f0, f1, f2 FROM test_table WHERE f0=3;
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table      | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test_table | NULL       | ref  | idx_f0_f1     | idx_f0_f1 | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+-------+

同时包含两者:Using where;Using Index的情况

在互联网上搜索相关信息,主要有两种观点:

[En]

Searching for relevant information on the Internet, there are two main views:

两种看法的分歧点就在于Using where是否表示需要回表查询数据,认为需要回表查数据的文档依据主要基于文档中的下述说明:

Using index
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.

If the Extra column also says Using where, it means the index is being used to perform lookups of key values. Without Using where, the optimizer may be reading the index to avoid reading data rows but not using it for lookups. For example, if the index is a covering index for the query, the optimizer may scan it without using it for lookups.

其关键在于第二段中:Without Using where,优化器将可以通过只读索引而避免进一步回表读取完整行数,所以我们正常理解Using where自然就意味着需要去回表读取行数据了。
然而实际上该文档说明来源于dev版MySQL5.1的文档,在5.6及以上版本的文档中已经没有该内容,而我在存档的Mysql5.1 官方文档MySQL 5.1 Reference Manual中也没有找到对应内容,其实际来源暂不可考,这里把讨论范围限于5.6及以上版本。
于是通过上面的Using where与Using Index的官方文档说明可以得出以下三点:

explain->using_where= MY_TEST(select && select->cond);

进一步佐证Using where即表示select包含条件子句。
sample:
如下sql仅涉及索引字段,但是要在where子句中对索引字段f0进行取余计算后才能比较条件,此种情况下无法直接在第一步查找索引时即进行条件判断,只能先把索引全部取出作为初步结果集,而后再进行where子句筛选:

EXPLAIN SELECT f0, f1 FROM test_table WHERE f0%2=0;
+----+-------------+------------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
| id | select_type | table      | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+------------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | test_table | NULL       | index | NULL          | idx_f0_f1 | 8       | NULL |    6 |   100.00 | Using where; Using index |
+----+-------------+------------+------------+-------+---------------+-----------+---------+------+------+----------+--------------------------+

如下sql则需要对索引字段f1通过LEFT函数取前缀后进行比较,同样只能先把索引全部取出作为初步结果集,而后再进行where子句筛选

EXPLAIN SELECT f0, f1 FROM test_table WHERE f0=3 AND LEFT(f1, 2)='33';
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
| id | select_type | table      | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra                    |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
|  1 | SIMPLE      | test_table | NULL       | ref  | idx_f0_f1     | idx_f0_f1 | 4       | const |    1 |   100.00 | Using where; Using index |
+----+-------------+------------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+

Original: https://www.cnblogs.com/AcAc-t/p/mysql_explain_difference_between_using_index_and_using_where.html
Author: 及时
Title: MySQL explain结果Extra中”Using Index”与”Using where; Using index”区别探究

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/507790/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • mysql精简单机版,免登录,可复制,不启动服务,与本机mysql无冲突

    突然有了个需要在本地使用的mysql需求,要求不用安装,随拷随用,不影响其他mysql服务,占用空间小.基于这种需求做了个精简版的mysql 首先下载mysql的zip安装包 wi…

    数据库 2023年5月24日
    097
  • Mysql的读写分离中间件该怎么写?听我来说。

    网上有很多读写分离的中间件,像proxy,mycat等等,由于本人比较懒,懒得去读各种开源的东西,还是想造轮子来得快。 1、了解mysql通信协议,其中有分4.1之前和4.1版本的…

    数据库 2023年5月24日
    0138
  • 03-MySQL事务

    数据库事务 1、事务特性 1.1、原子性 即不可分割性,事务要么全部被执行,要么就全部不被执行 1.2、一致性 事务的执行使得数据库从一种正确状态转换成另一种正确状态 1.3、隔离…

    数据库 2023年6月16日
    0122
  • Linux平台Redis安装总结

    本文测试验证的操作系统为CentOS Linux release 7.8.2003 (Core),Redis版本为redis-6.0.8。 敬请注意,如有不同,请以实际情况为准。 …

    数据库 2023年6月11日
    084
  • MySQL45讲之用户关注案例

    本文介绍 MySQL45 讲中提到的一个用户关注的案例,并记录下可行的处理方案。 业务背景 业务上有这样的需求,A、B两个用户,如果互相关注,则成为好友。存在两个表,关系(rela…

    数据库 2023年5月24日
    0154
  • 01-MySQL主从复制

    问题导入 在之前项目的基础功能实现中,后台管理和移动端在进行数据访问的时候,都是直接操作数据库MySQL。此时的系统有且仅有一台MySQL服务器,则可能会出现如下问题 ①、读和写所…

    数据库 2023年5月24日
    092
  • 开源、强大的Linux服务器集群管理工具,比宝塔好用!

    在这之前肯定很多人都接触过Linux管理面板:宝塔,宝塔的确非常方便而且好用,安装也简单,复制粘贴几句命令即可安装完成,且提供免费版。今天呢,民工哥向大家介绍另一个Linux的服务…

    数据库 2023年6月9日
    0186
  • 「 MySQL高级篇 」MySQL索引原理,设计原则

    404. 抱歉,您访问的资源不存在。 可能是URL不正确,或者对应的内容已经被删除,或者处于隐私状态。 [En] It may be that the URL is incorre…

    数据库 2023年5月24日
    0103
  • Netty-NIO基础

    一. NIO 基础 non-blocking io 非阻塞 IO 1. 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream,它就…

    数据库 2023年6月16日
    088
  • Matery主题自定义(一)黑夜模式

    黑夜模式 作为一个前端学习者,自然懂得黑夜模式的重要性,可惜主题原生未提供,那就自己弄吧 参考其他优秀产品的黑夜模式,得出共性: 那就是黑夜模式的背景一般不会是纯黑(#000);而…

    数据库 2023年6月16日
    084
  • 记一次部署系列:Mysql高可用之MHA

    参考:《Mysql高可用实践》——清华大学出版社2020年6月 环境:CentOS Linux release 7.7.1908 (Core) Mysql:…

    数据库 2023年5月24日
    0100
  • 系统设计的11个考虑

    有了《系统架构的11条原则》,真正到设计阶段还有另外11个考虑。 系统正确性 考虑一:负负得正 假如我们看到某个代码,明显有逻辑错误,想随手改改。你就要考虑一件事情:这段明显有问题…

    数据库 2023年6月6日
    097
  • win10搜索功能用不了

    这玩意搞了我今天,直接裂开!系统更新根本解决不了 好在查了相关资料才知道,原来微软在 Win10 的更新中,将搜索功能和语音助手 Cortana 进行了拆分,搜索成了一个独立的功能…

    数据库 2023年6月14日
    096
  • sql 优化

    对比 select * from A t1 left join B t2 on ( t1.c1 = t2.c1 or t1.c1=t2.c2) select * from A t1…

    数据库 2023年6月16日
    093
  • Maven的工作机制

    Maven是 Apache 软件基金会组织维护的一款专门为 Java 项目提供 构建和 依赖管理支持的工具。 ·首先, Maven核心程序:负责Maven的总体调度,具体操作使用的…

    数据库 2023年6月16日
    094
  • 创新能力加速产业发展,SphereEx 荣获“中关村银行杯”『大数据与云计算』领域 TOP1

    8 月 9 日下午,2022 中关村国际前沿科技创新大赛”中关村银行杯”大数据与云计算领域决赛在北京市门头沟区中关村(京西)人工智能科技园·智能文创园落下了…

    数据库 2023年6月16日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球