读懂MySQL执⾏计划sql执⾏计划详解(⾮常有⽤)
前⾔
在之前的⾯试过程中,问到执⾏计划,有很多童鞋不知道是什么?甚⾄将执⾏计划与执⾏时间认为是同⼀个概念。今天我们就⼀起来了解⼀下执⾏计划到底是什么?有什么⽤途?
执⾏计划是什么?
mysql面试题sql语句多表联查执⾏计划,简单的来说,是SQL在数据库中执⾏时的表现情况,通常⽤于SQL性能分析,优化等场景。在MySQL中使⽤ explain 关键字来查看。如下所⽰:
1.查询t_base_user
select * from t_base_user where name="andyqian";
2.查看上述语句的执⾏计划
explain select * from t_base_user where name="andyqian";
执⾏查看上述2语句后,我们可以得出以下执⾏计划
上⾯这个执⾏计划给到的信息是: 这是⼀个简单的SQL,全表扫描,共扫描1⾏,Using where条件在t_base_user表中筛选出记录。发现该语句并没有⾛索引,为什么是这样的呢?别急,我们紧接着看下⼀节。上⾯执⾏计划是什么意思呢?有什么参考价值呢?
读懂执⾏计划
通过上⾯,我们知道了什么是执⾏计划,也看到了执⾏计划到底是什么东西,现在我们来具体了解⼀下,MySQL执⾏计划中,每个属性代表的是什么意思?
我们⼀⼀来介绍,并说明每个属性有哪些可选值,以及每个可选值的意思。
id: 表⽰查询中select操作表的顺序,按顺序从⼤到依次执⾏
select_type :
该表⽰选择的类型,常见可选值有: SIMPLE(简单的), PRIMARY(最外层) ,SUBQUERY(⼦查询中的第⼀个select查询)
type :
该属性表⽰访问类型,有很多种访问类型。
最常见的其中包括以下⼏种: ALL(全表扫描), index(索引扫描),range(范围扫描),ref (⾮唯⼀索引扫描),eq_ref(唯⼀索引扫描,),(const)常数引⽤, 访问速度依次由慢到快。
其中 : range(范围)常见与 between and ..., ⼤于 and ⼩于这种情况。
提⽰ : 慢SQL是否⾛索引,⾛了什么索引,也就可以通过该属性查看了。
table :
旅游网站与政府网站表⽰输出⾏数据所在表
possible_keys :
顾名思义,该属性给出了,该查询语句,可能⾛的索引,(如某些字段上索引的名字)这⾥提供的只是参考,⽽不是实际⾛的索引,也就导致会有possible_Keys不为null,key为空的现象。
key : 显⽰MySQL实际使⽤的索引,其中就包括主键索引(PRIMARY),或者⾃建索引的名字。
key_len : 表⽰索引所使⽤的字节数,
ref :
连接匹配条件,如果⾛主键索引的话,该值为: const, 全表扫描的话,为null值
rows :
扫描⾏数,也就是说,需要扫描多少⾏,采能获取⽬标⾏数,⼀般情况下会⼤于返回⾏数。通常情况下,rows越⼩,效率越⾼, ⼤部分SQL优化,都是在减少这个值的⼤⼩。
注意: 理想情况下扫描的⾏数与实际返回⾏数理论上是⼀致的,但这种情况及其少,如关联查询,扫描的⾏数就会⽐返回⾏数⼤⼤增加)
java约瑟夫出圈详细教学Extra 这个属性⾮常重要,该属性中包括执⾏SQL时的真实情况信息,如上⾯所属,使⽤到的是"using where",表⽰使⽤where筛选得到的值,常⽤的有: "Using temporary": 使⽤临时表 "using filesort": 使⽤⽂件排序
看到这⾥,我们应该已经发现,在第⼀步中,我们的这条SQL
select * from t_base_user where name="andyqian";
是没有⾛索引的,⽽且还是全表扫描,在数据量少的情况下,问题还不会特别突出,如果数据量⽐较⼤,这可是个会造成⽣产事故的慢查询哦,现在我们改造⼀下,将name字段添加上索引,
添加索引
alter table t_base_user add index idx_name(name);
看看它的执⾏计划是怎样的。
你看, 现在已经⾛idx_name索引了,其type从All(全表扫描)到ref(⾮唯⼀索引了),别看就只有这⼀点点⼩区别,在⼤数据量的时候,可是会起⾄关重要的作⽤!
数据结构
本⽂中演⽰的数据结构如下:
create table t_base_user(
oid bigint(20) not null primary key auto_increment,
name varchar(30) null comment "name",
email varchar(30) null comment "email",
age int null comment "age",
telephone varchar(30) null comment "telephone",
status tinyint(4) null comment "0 ⽆效 1 有效",
created_at datetime null comment "",
updated_at datetime null comment ""
)
// 新增记录:
mysql的sql执⾏计划详解(⾮常有⽤)
引⾔:
实际项⽬开发中,由于我们不知道实际查询的时候数据库⾥发⽣了什么事情,数据库软件是怎样扫描表、怎样使⽤索引的,因此,我们能感知到的就只有
sql语句运⾏的时间,在数据规模不⼤时,查询是瞬间的,因此,在写sql语句的时候就很少考虑到性能的问题。但是当数据规模增⼤,如千万、亿的时候,我们运来一个网页示例
⾏同样的sql语句时却发现迟迟没有结果,这个时候才知道数据规模已经限制了我们查询的速度。所以,查询优化和索引也就显得很重要了。
问题:
当我们在查询前能否预先估计查询究竟要涉及多少⾏、使⽤哪些索引、运⾏时间呢?答案是能的,mysql提供了相应的功能和语法来实现该功能。
分析:
MySql提供了EXPLAIN语法⽤来进⾏查询分析,在SQL语句前加⼀个"EXPLAIN"即可。⽐如我们要分析如下SQL语句:
explain select * from table where table.id = 1
运⾏上⾯的sql语句后你会看到,下⾯的表头信息:
table | type | possible_keys | key | key_len | ref | rows | Extra
EXPLAIN列的解释
table
显⽰这⼀⾏的数据是关于哪张表的
type
这是重要的列,显⽰连接使⽤了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
说明:不同连接类型的解释(按照效率⾼低的顺序排序)
system:表只有⼀⾏:system表。这是const连接类型的特殊情况。
const :表中的⼀个记录的最⼤值能够匹配这个查询(索引可以是主键或惟⼀索引)。因为只有⼀⾏,这个值实际就是常数,因为MYSQL 先读这个值然后把它当做常数来对待。
eq_ref:在连接中,MYSQL在查询时,从前⾯的表中,对每⼀个记录的联合都从表中读取⼀个记录,它在查询使⽤了索引为主键或惟⼀键的全部时使⽤。
ref:这个连接类型只有在查询使⽤了不是惟⼀或主键的键或者是这些类型的部分(⽐如,利⽤最左边
前缀)时发⽣。对于之前的表的每⼀个⾏联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好。
range:这个连接类型使⽤索引返回⼀个范围中的⾏,⽐如使⽤>或<;查东西时发⽣的情况。
index:这个连接类型对前⾯的表中的每⼀个记录联合进⾏完全扫描(⽐ALL更好,因为索引⼀般⼩于表数据)。
ALL:这个连接类型对于前⾯的每⼀个记录联合进⾏完全扫描,这⼀般⽐较糟糕,应该尽量避免。
possible_keys
rgb颜生成器显⽰可能应⽤在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择⼀个合适的语句
key
实际使⽤的索引。如果为NULL,则没有使⽤索引。很少的情况下,MYSQL会选择优化不⾜的索引。这种情况下,可以在SELECT语句中使⽤USE INDEX(indexname)来强制使⽤⼀个索引或者⽤IGNORE INDEX(indexname)来强制MYSQL忽略索引
key_len
使⽤的索引的长度。在不损失精确性的情况下,长度越短越好
ref
显⽰索引的哪⼀列被使⽤了,如果可能的话,是⼀个常数html在线生成代码
rows
MYSQL认为必须检查的⽤来返回请求数据的⾏数
Extra
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论,但这⾥可以看到的坏的例⼦是Using temporary和Using filesort,意思MYSQL根本不能使⽤索引,结果是检索会很慢
说明:extra列返回的描述的意义
Distinct :⼀旦mysql到了与⾏相联合匹配的⾏,就不再搜索了。
Not exists :mysql优化了LEFT JOIN,⼀旦它到了匹配LEFT JOIN标准的⾏,就不再搜索了。
Range checked for each Record(index map:#) :没有到理想的索引,因此对从前⾯表中来的每⼀个⾏组合,mysql检查使⽤哪个索引,并⽤它来从表中返回⾏。这是使⽤索引的最慢的连接之⼀。
Using filesort :看到这个的时候,查询就需要优化了。mysql需要进⾏额外的步骤来发现如何对返回的⾏排序。它根据连接类型以及存储排序键值和匹配条件的全部⾏的⾏指针来排序全部⾏。
Using index :列数据是从仅仅使⽤了索引中的信息⽽没有读取实际的⾏动的表返回的,这发⽣在对表的全部的请求列都是同⼀个索引的部分的时候。
Using temporary :看到这个的时候,查询需要优化了。这⾥,mysql需要创建⼀个临时表来存储结果,这通常发⽣在对不同的列集进⾏ORDER BY上,⽽不是GROUP BY上。
Where used :使⽤了WHERE从句来限制哪些⾏将与下⼀张表匹配或者是返回给⽤户。如果不想返回表中的全部⾏,并且连接类型ALL或index,这就会发⽣,或者是查询有问题。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论