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)

大家都在看

  • centos7安装docker

    一、安装前必读 在安装 Docker 之前,先说一下配置,我这里是Centos7 Linux 内核:官方建议 3.10 以上,3.8以上貌似也可。 注意:本文的命令使用的是 roo…

    数据库 2023年6月14日
    0112
  • 09 子查询

    数据库关联子查询和非关联子查询 非关联子查询:数据库嵌套查询中内层查询是完全独立于外层查询的。 执行顺序: 先执行内层查询 得到内层查询的结果后带入外层,再执行外层查询 selec…

    数据库 2023年6月16日
    0135
  • 有趣的BUG之Stack Overflow

    今天遇到一个很有意思的bug,当程序开发完成后打包到服务器运行,总是会出现栈溢出异常,经过排查发现,问题出现在一个接口上,但这个接口逻辑并不复杂,除了几局逻辑代码外和打印语句之外也…

    数据库 2023年6月6日
    0122
  • 你的 SQL 还在回表查询吗?快给它安排覆盖索引

    什么是回表查询 小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键、聚集索引、辅助索引,简单回顾下,聚集索引的叶子节点包含完整的行数据,而非聚集索引…

    数据库 2023年5月24日
    0115
  • JavaScript详解

    一、快速入门 1.JavaScript的两种引入方式 方式一:直接在html里面写 目的:实现简单的弹窗 点击查看代码 <!DOCTYPE html> <html…

    数据库 2023年6月16日
    0115
  • 第二十章 AOP开发中的坑

    问题 //在同一个业务类中,一个业务方法调用另一个业务方法 //问题: login方法添加有额外功能 // register方法没有添加额外功能 public class User…

    数据库 2023年6月14日
    0110
  • MySQL备份迁移之mydumper

    简介 mydumper 是一款开源的 MySQL 逻辑备份工具,主要由 C 语言编写。与 MySQL 自带的 mysqldump 类似,但是 mydumper 更快更高效。mydu…

    数据库 2023年5月24日
    0165
  • 红黑树添加删除

    上一篇写了234树对比红黑树,和红黑树某些情况需要调整的原因,这篇就只写红黑树的添加和删除 红黑树 JAVA技术交流群:737698533 性质 每个节点要么红色要么黑色 根节点是…

    数据库 2023年6月16日
    090
  • 记一次部署系列:prometheus配置通过alertmanager进行邮件告警

    1、修改配置 首先在prometheus中配置alertmanager地址,并配置告警规则文件,如下,然后重启prometheus。 规则文件如下:rules.yml &#8211…

    数据库 2023年6月9日
    0100
  • Mybatis的级联查询,分步查询,一对一,一对多和多对一

    配置和代码目录 ***util配置 ***log4j配置 –可以打印入日志,也可以使用系统自带的STDOUT_LOGGING个人喜欢log4j ***mybatis-c…

    数据库 2023年5月24日
    0117
  • 国内访问github很慢或者访问不了,解决办法

    国内因为某些问题,会屏蔽国外一些网站。有时GitHub访问的时候会出现错误,无法访问。解决办法 进入https://fastly.net.ipaddress.com/(全球最好的I…

    数据库 2023年6月6日
    0160
  • 9.回文数

    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,而…

    数据库 2023年6月16日
    097
  • SQL Server2008 Order by在union子句不可直接使用的原因

    按照要求,每个取top 20,既然是随机的取,那么就SQL Server Order by newid()就是了,然后把所有数据union起来就得了。所以我立即给出了答案: sel…

    数据库 2023年6月14日
    0109
  • Linux 的基本操作 -权限

    Linux 的基本操作 -权限 权限:文件的属性: d:表示目录-:表示文件 l:连接文件 b:设备文件,提供存储的接口设备 c:设备文件,提供串行的接口设备–键盘,鼠…

    数据库 2023年6月16日
    0123
  • 面试题: 字符串转整型 终结者

    随着代码手感增强, 想为这个问题写个终结者系列. 缅怀下曾经的自己. 我们审视下这个问题, 整数字符串转成整数. 那么意味着有效字符仅有 “+-0123456789&#…

    数据库 2023年6月9日
    0125
  • MySQL 主从同步延迟监控

    MySQL5.7和8.0支持通过 replication_applier_status 表获同步延迟时间,当从库出现延迟后,该表中的字段 REMAINING_DELAY 记录延迟秒…

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