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)

大家都在看

  • 计算字符串中连续出现最多的字符串和长度

    public static void main(String[] args) { // 定义的字符&#x4E3…

    数据库 2023年6月11日
    089
  • MSQL–>存储引擎

    概述 MySQL体系结构图 Innodb引擎是在mysql的5.5版本之后的默认存储引擎。 Index是在引擎层次的,不同的存储引擎index的用法不同。 存储引擎就是存储数据,建…

    数据库 2023年6月14日
    084
  • SQL与数据库编程学习笔记——day3

    SQL与数据库编程学习笔记-day3 增加语句; 利用insert into语句进行增加数据库数据; 格式: insert into 表名 (字段名) values (数值);ps…

    数据库 2023年6月9日
    0126
  • MySQL索引(一)

    一、索引概念 二、索引类型 (一)业务逻辑分类 1、NORMAL – 普通索引 2、UNIQUE – 唯一索引 3、PRIMARY KEY – …

    数据库 2023年6月16日
    092
  • Java 中的异常处理机制

    本篇文章主要介绍了 Java 中的异常 如何处理函数抛出的异常 处理异常的原则 异常处理时,性能开销大的地方 Java 语言在设计之初就提供了相对完善的异常处理机制。 我们首先介绍…

    数据库 2023年6月11日
    0101
  • web开发模式

    前后端不分离 返回的是html的内容,需要在服务端拿到数据库的数据,再渲染给模板层,最后将渲染好的模板返回给浏览器! 前后端分离 前后端分离:只需要在浏览器上运行JS代码,使用aj…

    数据库 2023年6月14日
    089
  • Python–模块Module

    1、定义模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件,(文件名:test.py,对应的模块名test)包:用来…

    数据库 2023年6月9日
    081
  • Mysql索引底层数据结构与算法

    一.索引概述是什么:索引是帮助MySQL高效获取数据的排好序的数据结构,索引叫”键”,优化好一个索引,可以提高数倍的性能, 类似于字典的音序表为什么要键索引…

    数据库 2023年6月11日
    0108
  • CronExpression使用笔记

    CronExpression一般是使用在自动任务中,可以指定任务执行的时间或者时间规律,下面记录一下表达试的使用说明 CronExpression由7个子表达式组成,7个子表达式之…

    数据库 2023年6月9日
    099
  • MySQL中读页缓冲区buffer pool

    Buffer pool 我们都知道我们读取页面是需要将其从磁盘中读到内存中,然后等待CPU对数据进行处理。我们直到从磁盘中读取数据到内存的过程是十分慢的,所以我们读取的页面需要将其…

    数据库 2023年5月24日
    0106
  • ReentrantLock 公平锁源码 第2篇

    Reentrant 2 前两篇写完了后我自己研究了下,还有有很多疑惑和问题,这篇就继续以自问自答的方式写 如果没看过第1篇的可以先看看那个https://www.cnblogs.c…

    数据库 2023年6月16日
    074
  • SpringBoot接口方法调用过程分析

    前言 本文主要通过调试的方法来分析 SpringBoot 接口方法的大致调用过程,从调用流程层面简单地分析下源码,不进行深入解读。此外,本文调试使用的是 SpringBoot 的 …

    数据库 2023年6月9日
    0149
  • Yapi安装配置(CentOs)

    环境要求 nodejs(7.6+)mongodb(2.6+)git 准备工作 清除yum命令缓存 sudo yum clean all 卸载低版本nodejs yum remove…

    数据库 2023年6月11日
    070
  • Activiti7 多实例子流程

    顾名思义,子流程是一个包含其他活动、网关、事件等的活动,这些活动本身形成了一个流程,该流程是更大流程的一部分。 使用子流程确实有一些限制: 一个子流程只能有一个none类型的启动事…

    数据库 2023年6月14日
    0152
  • Dubbo源码(二)-SPI源码

    假设你已经知道Dubbo SPI的使用方式,不知道的请出门左转: Dubbo源码地址: 本文使用版本:2.6.x 获取所有的拓展类 Dubbo SPI 的相关逻辑被封装在了 Ext…

    数据库 2023年6月11日
    078
  • MySQL实战45讲 10

    10 | MySQL为什么有时候会选错索引? 使用哪个索引是由 MySQL 来确定的 可能遇到的情况:一条本来可以执行得很快的语句,却由于 MySQL 选错了索引,而导致执行速度变…

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