MySQL执行计划extra中的using index 和 using where using index 的区别
本文出处:http://www.cnblogs.com/wy123/p/7366486.html
(保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他)
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)
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
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条件的过滤,
反过来说,也就是没有可用的索引查找,当然这里也要考虑索引扫描+回表与表扫描的代价。
这里的type都是all,说明MySQL认为全表扫描是一种比较低的代价。
Using index condition
1,查询的列不全在索引中,where条件中是一个前导列的范围
2,查询列不完全被索引覆盖,查询条件完全可以使用到索引(进行索引查找)
参考: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语句执行的,即便是索引前导列的索引范围查找也有一点范围扫描的动作,不管是前非索引前导列引起的,还是非索引列查询引起的。
20200313补充,这里有一个很经典的例子,会出现using index condition;using where的情况,这种情况暂时不知道怎么去解释,按道理也不是ICP??
https://juejin.im/post/5cef832e5188257c6b516d1f
using index condition;using where出现的时候,实际上是分两步
1,第一步是ICP,在存储引擎层发生的
2,第二步是using where,是在server层过滤的。
尚未解决的问题:
查询1
查询2
查询3(逻辑上等价于查询1+查询2),执行计划发生了很大的变化。
总结:
MySQL执行计划中的Extra中信息非常多,不仅仅包括Using index,Using where Using index,Using index condition,Using where,尤其是在多表连接的时候,这一点在相对MSSQL来说,不够直观或者结构化。
MSSQL中是通过区分索引查找(index seek),索引扫描(index scan),表扫描(table scan)来实现具体的查询的,这图形化的执行计划在不同的场景下是非常直观的,要想完全弄懂MySQL的这个执行计划,可能要更多地在实践中摸索。
MySQL执行计划extra中的using index 和 using where using index 的区别的更多相关文章
- MySQL 执行计划中Extra(Using where,Using index,Using index condition,Using index,Using where)的浅析
关于如何理解MySQL执行计划中Extra列的Using where.Using Index.Using index condition,Using index,Using where这四者的区别 ...
- MySQL explain结果Extra中"Using Index"与"Using where; Using index"区别探究
问题背景 最近用explain命令分析查询sql执行计划,时而能看到Extra中显示为"Using index"或者"Using where; Using Index&q ...
- MySQL执行计划解读
Explain语法 EXPLAIN SELECT …… 变体: 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得 ...
- mysql执行计划
烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长.如何写好sql,学会看执行计划至关重要.下面我简单讲讲mysql的执行计划,只列出了一些常见的情况, ...
- 如何查看MySQL执行计划
在介绍怎么查看MySQL执行计划前,我们先来看个后面会提到的名词解释: 覆盖索引: MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件 包含所有满足查询需要的数据的索引 ...
- MySQL执行计划 EXPLAIN参数
MySQL执行计划参数详解 转http://www.jianshu.com/p/7134286b3a09 MySQL数据库中,在SELECT查询语句前边加上“EXPLAIN”或者“DESC”关键字,即 ...
- 查看Mysql执行计划
使用navicat查看mysql执行计划: 打开profile分析工具: 查看是否生效:show variable like ‘%profil%’; 查看进程:show processlist; 选择 ...
- MySQL 执行计划explain详解
MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...
- MYSQL 执行计划
Explain语法 EXPLAIN SELECT …… 变体: 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得 ...
随机推荐
- 再谈AbstractQueuedSynchronizer:基于AbstractQueuedSynchronizer的并发类实现
公平模式ReentrantLock实现原理 前面的文章研究了AbstractQueuedSynchronizer的独占锁和共享锁,有了前两篇文章的基础,就可以乘胜追击,看一下基于AbstractQue ...
- Vijos 1004 伊甸园日历游戏 博弈
描述 Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来.然后他们轮流对这个日期进行操作: 1 : 把日期的天数加1,例如1900.1.1变到19 ...
- 拥抱.NET Core系列:依赖注入(1)
依赖注入时编程手段中解耦和封装的一个非常重要的手段,我本人已经到了没有DI无法编写项目的程度了,在.NET Framework中微软并没有在FCL中引入DI,虽然推出了"Unity" ...
- python简单实现websocket
协议选择的是新的Hybi-10,参考文章如下: http://www.cnblogs.com/zhuweisky/p/3930780.html http://blog.mycolorway.com/2 ...
- vijos1047题解
总算编好了这一题,我表示200+行,亚历山大. 题目描述很简单,做起来不简单啊.(高精度的取模和除法不是一般的恶心!) 先说一下非高精度的一般做法. 求两个数a,b的最小公倍数,就是a.b的乘积与a. ...
- string can not be resolved
参考:http://jingyan.baidu.com/article/a17d5285339c828099c8f245.html
- .net控件Radiobuttonlist的简单应用
1.radiobuttonlist 通过RepeatDirection属性控制改控件的显示方向是纵向还是横向. 2.radiobuttonlist有一个重要的时间叫OnSelectedIndexCha ...
- 图片预加载之模拟img.load()
function imgBatchLoad(){ var instance = this; this.loadCount = 0; this.images = []; this.imgCount = ...
- new/delete 与 malloc/free的区别
一.概述 在C++中,申请动态内存与释放动态内存用new/delete 与 malloc/free都可以,而且他们的存储方式相同,new/malloc申请的动态内存位于堆中,无法被操作系统自动 ...
- Android5.1 - 通讯录建立群组
[问题] 在没有账户的时候,不应该有添加联系人群组的选项. 我们要把这个选项干掉. [相关log]06-23 17:25:00.804: E/GroupEditorFragment(6030): No ...