mysql执行计划extra为null_MySQL执行计划extra中的using index 和 using where using index 的区别...

mysql执行计划中的extra列中表明了执行计划的每一步中的实现细节,其中包含了与索引相关的一些细节信息

其中跟索引有关的using index 在不同的情况下会出现Using index, Using where Using index ,Using index condition等

那么Using index 和 Using where;Using index 有什么区别?网上搜了一大把文章,说实在话也没怎么弄懂,于是就自己动手试试。

本文仅从最简单的单表去测试using index 和 using where using index以及简单测试using index condition的情况的出现时机 。

执行计划的生成与表结构,表数据量,索引结构,统计信息等等上下文等多种环境有关,无法一概而论,复杂情况另论。

测试环境搭建

测试表以及测试数据搭建,类似于订单表和订单明细表,暂时先用订单表做测试

测试表结构

create table test_order

(

id int auto_increment primarykey,user_id int,order_id int,order_status tinyint,create_date datetime

);

create table test_orderdetail

(

id int auto_increment primarykey,order_id int,product_name varchar(100),cnt int,create_date datetime

);

create index idx_userid_order_id_createdate on test_order(user_id,order_id,create_date);

create index idx_orderid_productname on test_orderdetail(order_id,product_name);

测试数据(50W)

CREATE DEFINER=`root`@`%` PROCEDURE `test_insertdata`(IN `loopcount` INT)

LANGUAGE SQL

NOT DETERMINISTIC

CONTAINS SQL

SQL SECURITY DEFINER

COMMENT''BEGINdeclare v_uuid varchar(50);while loopcount>0 doset v_uuid=uuid();

insert into test_order (user_id,order_id,order_status,create_date) values (rand()*1000,id,rand()*10,DATE_ADD(NOW(), INTERVAL - RAND()*20000HOUR));

insert into test_orderdetail(order_id,product_name,cnt,create_date) values (rand()*100000,v_uuid,rand()*10,DATE_ADD(NOW(), INTERVAL - RAND()*20000HOUR));

set loopcount= loopcount -1;end while;END

Using index VS Using where Using index

首先,在"订单表"上,这里是一个多列复合索引

create index idx_userid_order_id_createdate on test_order(user_id,order_id,create_date);

Using index

1,查询的列被索引覆盖,并且where筛选条件是索引的是前导列,Extra中为Using index

51cf77167fb2abef46c574be7d2399c0.png

Using where Using index

1,查询的列被索引覆盖,并且where筛选条件是索引列之一但是不是索引的不是前导列,Extra中为Using where; Using index,

意味着无法直接通过索引查找来查询到符合条件的数据

6b316c7ce0c4c7f2ff5a75260c0b15f2.png

2,查询的列被索引覆盖,并且where筛选条件是索引列前导列的一个范围,同样意味着无法直接通过索引查找查询到符合条件的数据

c1847c6f2ed24a9fc21cc50fc9d6fb37.png

NULL(既没有Using index,也没有Using where Using index,也没有using where)

1,查询的列未被索引覆盖,并且where筛选条件是索引的前导列,

意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引,Extra中为NULL(没有信息)

e4058e3050ef8e26fd9ba626ede7dfac.png

Using where

1,查询的列未被索引覆盖,where筛选条件非索引的前导列,Extra中为Using where

6624f73c20b27a167b5b8ac2e52247ac.png

2,查询的列未被索引覆盖,where筛选条件非索引列,Extra中为Using where

b7029b06cfa0b456284efab0897a84fd.png

using where 意味着通过索引或者表扫描的方式进程where条件的过滤,

反过来说,也就是没有可用的索引查找,当然这里也要考虑索引扫描+回表与表扫描的代价。

这里的type都是all,说明MySQL认为全表扫描是一种比较低的代价。

Using index condition

1,查询的列不全在索引中,where条件中是一个前导列的范围

0fc51b01b7703bfeab4b13e54e53adf0.png

2,查询列不完全被索引覆盖,查询条件完全可以使用到索引(进行索引查找)

dbbc97e0e6235db1efd812078169586d.png

参考:MySQL · 特性分析 · Index Condition Pushdown (ICP)

using index conditoin 意味着查询列的某一部分无法直接使用索引

上述case1中,

如果禁用ICP(set optimizer_switch='index_condition_pushdown=off'),

执行计划是using where,意味着全表扫描,如果启用ICP,执行计划为using index Condition,意味着在筛选的过程中实现过滤

上述case1中

第二个查询条件无法直接使用索引,隐含了一个查找+筛选的过程。

两个case的共同点就是无法直接使用索引。

结论:

1,Extra中的为Using index的情况

where筛选列是索引的前导列 &&查询列被索引覆盖 && where筛选条件是一个基于索引前导列的查询,意味着通过索引超找就能直接找到符合条件的数据,并且无须回表

2,Extra中的为空的情况

查询列存在未被索引覆盖&&where筛选列是索引的前导列,意味着通过索引超找并且通过“回表”来找到未被索引覆盖的字段,

3,Extra中的为Using where Using index:

出现Using where Using index意味着是通过索引扫描(或者表扫描)来实现sql语句执行的,即便是索引前导列的索引范围查找也有一点范围扫描的动作,不管是前非索引前导列引起的,还是非索引列查询引起的。

尚未解决的问题:

查询1

f5a0228730deb3177d2900bdc0d34b5d.png

查询2

1e73a5edd35a51207a7856ae704613da.png

查询3(逻辑上等价于查询1+查询2),执行计划发生了很大的变化。

21004d1583a7ccc539905219c913b8ba.png

总结:

MySQL执行计划中的Extra中信息非常多,不仅仅包括Using index,Using where Using index,Using index condition,Using where,尤其是在多表连接的时候,这一点在相对MSSQL来说,不够直观或者结构化。

MSSQL中是通过区分索引查找(index seek),索引扫描(index scan),表扫描(table scan)来实现具体的查询的,这图形化的执行计划在不同的场景下是非常直观的,要想完全弄懂MySQL的这个执行计划,可能要更多地在实践中摸索。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL,您可以使用`EXPLAIN`语句来查看查询语句的执行计划。使用`EXPLAIN`语句可以帮助您分析查询语句的性能,找出潜在的性能问题,并优化查询语句。 使用`EXPLAIN`语句的语法如下: ``` EXPLAIN SELECT column1, column2, ... FROM table_name WHERE condition; ``` 其,`SELECT`语句是您要分析的查询语句。`column1, column2, ...`是您要检索的列名,`table_name`是您要查询的表名,`condition`是您要应用的条件。 当您执行`EXPLAIN`语句时,MySQL会返回一个描述查询执行计划的结果集。每一行都代表查询执行计划的一个步骤,称为“访问类型”。以下是常见的访问类型: - `SIMPLE`:简单查询,不使用联接或子查询。 - `PRIMARY`:查询从主表获取行。 - `UNIQUE`:查询从唯一索引获取行。 - `FULLTEXT`:查询从全文索引获取行。 - `DERIVED`:派生表,为 FROM 子句的子查询创建临时表。 - `SUBQUERY`:子查询,使用 IN、EXISTS 或量词比较运算符的子查询。 在每一行,您还可以看到其他有关查询执行计划的信息,例如使用的索引,扫描的行数,排序方式等。 例如,以下是查询`employees`表的所有员工,并使用`EXPLAIN`查看查询执行计划的示例: ``` EXPLAIN SELECT * FROM employees; ``` 执行上述语句后,您将看到类似于以下输出的结果: ``` +----+-------------+-----------+-------+---------------+---------+---------+------+------+----------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+-------+---------------+---------+---------+------+------+----------+-------------+ | 1 | SIMPLE | employees | index | NULL | PRIMARY | 4 | NULL | 1000 | 100.00 | Using index | +----+-------------+-----------+-------+---------------+---------+---------+------+------+----------+-------------+ ``` 在上面的结果,您可以看到查询使用了`PRIMARY`索引,并且扫描了1000行。`Extra`列提供了其他有关查询执行计划的信息,例如是否使用了索引,是否使用了临时表等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值