博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL执行计划extra中的using index 和 using where; using index 的区别
阅读量:4186 次
发布时间:2019-05-26

本文共 2783 字,大约阅读时间需要 9 分钟。

转自:   侵删

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 primary key,    user_id int,    order_id int,    order_status tinyint,    create_date datetime);create table test_orderdetail(    id int auto_increment primary key,    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)
DELIMITER //  CREATE DEFINER=`root`@`%` PROCEDURE `test_insertdata`(IN `loopcount` INT)    LANGUAGE SQL    NOT DETERMINISTIC    CONTAINS SQL    SQL SECURITY DEFINER    COMMENT ''BEGIN    declare v_uuid  varchar(50);    while loopcount>0 do        set 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()*20000 HOUR));        insert into test_orderdetail(order_id,product_name,cnt,create_date) values (rand()*100000,v_uuid,rand()*10,DATE_ADD(NOW(), INTERVAL - RAND()*20000 HOUR));        set loopcount = loopcount -1;    end while;END //DELIMITER ;call test_insertdata(500000);

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

Using where Using index

1,查询的列被索引覆盖,并且where筛选条件是索引列之一但是不是索引的不是前导列,Extra中为Using where; Using index,意味着无法直接通过索引查找来查询到符合条件的数据

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

   

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

1,查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引,Extra中为NULL(没有信息)

Using where

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

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

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

 Using index condition

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

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

  参考:

多表关联的时候Using index condition出现的情况更多,目前还不怎么理解Using index condition的内部实现模式。

 

结论:

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

2,Extra中的为空的情况

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

3,Extra中的为Using where Using index: 

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

 

尚未解决的问题:

     查询1

查询2

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

 

转载地址:http://zbdoi.baihongyu.com/

你可能感兴趣的文章