关于如何理解mysql执行计划中Extra列的Using where、Using Index、Using index condition,Using index,Using where这四者的区别。首先,我们来看看官方文档关于三者的简单介绍(官方文档并没有介绍Using index,Using where这种情况):

Using index (JSON property: 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.

For InnoDB tables that have a user-defined clustered index, that index can be used even when Using index is absent from the Extra column. This is the case if type is index and key is PRIMARY.

从表中仅使用索引树中的信息就能获取查询语句的列的信息, 而不必进行其他额外查找(seek)去读取实际的行记录。当查询的列是单个索引的部分的列时, 可以使用此策略。(简单的翻译就是:使用索引来直接获取列的数据,而不需回表)。对于具有用户定义的聚集索引的 InnoDB 表, 即使从Extra列中没有使用索引, 也可以使用该索引。如果type是index并且Key是主键, 则会出现这种情况。

Using where (JSON property: attached_condition)

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 .

Using where has no direct counterpart in JSON-formatted output; the attached_condition property contains any WHERE condition used.

where 子句用于限制与下一个表匹配的行记录或发送到客户端的行记录。除非您特意打算从表中提取或检查所有行,否则如果Extra值不是Using where并且表连接类型为ALL或index,则查询可能会出错。

Using index condition (JSON property: using_index_condition)

Tables are read by accessing index tuples and testing them first to determine whether to read full table rows. In this way, index information is used to defer (“push down”) reading full table rows unless it is necessary. See Section 8.2.1.5, “Index Condition Pushdown Optimization” .

在展开讲述这些之前,我们先来回顾一下执行计划中的Type与Extra部分内容。因为下面很多部分都需要这方面的知识点(其实最上面有些有关Extra的描述看起来很生涩,感觉不是那么通熟易懂!)

Type 的相关知识点:


MySQL 执行计划中Extra(Using where,Using index,Using index condition,Using index, ...

由左至右,性能由最差到最好

ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行

index:Full Index Scan,index与ALL区别为index类型只遍历索引树

range:索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询

ref:非唯一性索引扫描,返回匹配某个单独值的所有行。常见于使用非唯一索引即唯一索引的非唯一前缀进行的查找

eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描

const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量

NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引

Extra 的相关知识点:

Using temporary

表示MySQL需要使用临时表来存储结果集,常见于排序和分组查询

Using filesort

MySQL中无法利用索引完成的排序操作称为 “ 文件排序 ”

Using Index

表示直接访问索引就能够获取到所需要的数据(覆盖索引 ) ,不需要通过索引回表;

覆盖索引 : 如果一个索引包含(或者说覆盖)所有需要查询的字段的值。我们称之为 “ 覆盖索引 ” 。如果索引的叶子节点中已经包含要查询的数据,那么还有什么必要再回表查询呢?

Using Index Condition

在MySQL 5.6版本后加入的新特性(Index Condition Pushdown);会先条件过滤索引,过滤完索引后找到所有符合索引条件的数据行,随后用 WHERE 子句中的其他条件去过滤这些数据行;

Using where

表示MySQL服务器在存储引擎收到记录后进行 “ 后过滤 ” (Post-filter),如果查询未能使用索引,Using where的作用只是提醒我们MySQL将用where子句来过滤结果集。 这个一般发生在MySQL服务器,而不是存储引擎层 。一般发生在不能走索引扫描的情况下或者走索引扫描,但是有些查询条件不在索引当中的情况下。

下面我们通过实验来测试、验证一下,并加深一下我们对这些概念的理解,测试环境数据库为Sakila, 首先使用下面脚本准备测试环境:

CREATETABLE TEST( i1 INTNOTNULLDEFAULT 0, i2 INTNOTNULLDEFAULT 0, d DATEDEFAULTNULL, f INT default 0, PRIMARYKEY (i1, i2) ) ENGINE = InnoDB; INSERT INTO TEST VALUES (1, 1, '1998-01-01',1), (1, 2, '1999-01-01',2), (1, 3, '2000-01-01',1), (1, 4, '2001-01-01',2), (1, 5, '2002-01-01',1), (2, 1, '1998-01-01',2), (2, 2, '1999-01-01',1), (2, 3, '2000-01-01',2), (2, 4, '2001-01-01',1), (2, 5, '2002-01-01',2), (3, 1, '1998-01-01',1), (3, 2, '1999-01-01',2), (3, 3, '2000-01-01',1), (3, 4, '2001-01-01',2), (3, 5, '2002-01-01',1), (4, 1, '1998-01-01',2), (4, 2, '1999-01-01',1), (4, 3, '2000-01-01',2), (4, 4, '2001-01-01',1), (4, 5, '2002-01-01',2), (5, 1, '1998-01-01',1), (5, 2, '1999-01-01',2), (5, 3, '2000-01-01',1), (5, 4, '2001-01-01',2), (5, 5, '2002-01-01',1);

Extra中为Using where的情况

Extra中出现 “ Using where ” ,通常来说,意味着全表扫描或者在查找使用索引的情况下,但是还有查询条件不在索引字段当中。具体来说有很多种情况,下面简单罗列一下测试过程中遇到的各种情况(部分案例)。

1: 查询条件中的相关列,不是索引字段, 全表扫描后,通过Using where过滤获取所需的数据。

通俗来说,因为字段D没有索引,所以必须全表扫描,然后在服务器层使用WHERE过滤数据。

mysql> EXPLAIN -> SELECTCOUNT(*) FROM TEST WHERE D = '2000-01-01'; +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | TEST | ALL | NULL | NULL | NULL | NULL | 25 | Usingwhere | +----+-------------+-------+------+---------------+------+---------+------+------+-------------+ 1 rowinset (0.00 sec)

2 : (type=ref)非唯一性索引扫描,但是由于索引未覆盖所有查询条件(字段d并未包含在聚集索引 PRIMARY 中 ),在存储引擎返回记录后,仍然需要过滤数据(排除d != '2000-01-01'的数据)。

mysql> EXPLAIN -> SELECTCOUNT(*) FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | PRIMARY | PRIMARY | 4 | const | 5 | Usingwhere | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 1 rowinset (0.00 sec) mysql> mysql> EXPLAIN -> SELECT * FROM TEST WHERE i1 = 3 AND d = '2000-01-01'; +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ | 1 | SIMPLE | TEST | ref | PRIMARY | PRIMARY | 4 | const | 5 | Usingwhere | +----+-------------+-------+------+---------------+---------+---------+-------+------+-------------+ 1 rowinset (0.00 sec) mysql> mysql> EXPLAIN -> SELECTCOUNT(i1) FROM TEST WHERE i1 = 3 AND d = '20

本文数据库(mysql)相关术语:navicat for mysql mysql workbench mysql数据库 mysql 存储过程 mysql安装图解 mysql教程 mysql 管理工具

代码区博客精选文章
分页:12
转载请注明
本文标题:MySQL 执行计划中Extra(Using where,Using index,Using index condition,Using index, ...
本站链接:https://www.codesec.net/view/610673.html


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(mysql) | 评论(0) | 阅读(97)