SQL优化之MySQL执行计划(Explain)及索引失效详解

1、执行计划基础

1.1、执行计划(Explain)定义

在 MySQL 中可以通过 explain 关键字模拟优化器执行 SQL语句,从而解析MySQL 是如何处理 SQL 语句的。

1.2、MySQL查询过程

  1. 客户端向 MySQL 服务器发送一条查询请求
  2. 服务器首先检查查询缓存,如果命中缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段
  3. 服务器进行 SQL 解析、预处理、之后由优化器生成对应的执行计划
  4. MySQL 根据执行计划,调用存储引擎的 API 来执行查询
  5. 将结果返回给客户端,同时缓存查询结果

注意:只有在MySQL8.0之前才有查询缓存,MySQL8.0之后查询缓存被去掉了

1.3、启动执行计划

explain select 投影列 FROM 表名 WHERE 条件 ;

举例:

explain select * from teacher;

在这里插入图片描述

1.4、执行计划参数简介

在这里插入图片描述

2、实战解析

2.1、创建示例表

-- 课程表
create table course
(
cid int(3),
cname varchar(20),
tid int(3)
);
-- 教师表
create table teacher
(
    tid int(3),
    tname varchar(20),
    tcid int(3)
);
-- 教师证表
create table teacherCard
(
    tcid int(3),
    tcdesc varchar(200)
);

在这里插入图片描述
explain + select语句分析:

explain select * from teacher;

SQL执行计划结果:
在这里插入图片描述

2.2、执行计划参数详解

1、id

查询执行顺序:

  • id 值相同时表示从上向下执行
  • id 值相同被视为一组
  • 如果是子查询,id 值会递增,id 值越高,优先级越高
  • id为NULL最后执行

2、select_type

  • simple:表示查询中不包含子查询或者 union
  • primary:当查询中包含任何复杂的子部分,最外层的查询被标记成 primary
  • derived:在 from 的列表中包含的子查询被标记成 derived
  • subquery:在 select 或 where 列表中包含了子查询,则子查询被标记成 subquery
  • union:两个 select 查询时前一个标记为 PRIMARY,后一个标记为 UNION。union 出现在 from 从句子查询中,外层 select 标记为 PIRMARY,union 中第一个查询为 DERIVED,第二个子查询标记为 UNION
  • unionresult:从 union 表获取结果的 select 被标记成 union result 。

3、table

显示这一行的数据是关于哪张表的。当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。

4、type

这是重要的参数,显示连接使用了何种类型。
SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 const 最好。
说明如下:

  • const 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
  • ref 指的是使用普通的索引(normal index)。
  • range 对索引进行范围检索。
  • 从最好到最差的连接类型为 system > const > eq_reg > ref > range > index > ALL。
  • 一般来说,得保证查询达到range级别,最好达到ref。
  • NULL:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表。
  • system:表中只有一行数据。属于 const 的特例。如果物理表中就一行数据为 ALL。
  • const :查询结果最多有一个匹配行。因为只有一行,所以可以被视为常量。const 查询速度非常快,因为只读一次。一般情况下把主键或唯一索引作为唯一条件的查询都是 const
  • eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。
  • ref:非唯一性索引扫描,返回匹配某个单独值得所有行。索引要和某个值相比较,可能会找到多个符合条件的行。
  • range:把这个列当作条件只检索其中一个范围。常见 where 从句中出现 between、<、>、>=、in 等。主要应用在具有索引的列中。
  • index:full index scan全索引扫描,index与all的区别为:index类型只遍历索引树,这通常比all快,因为索引文件通常比数据文件小。也就是说虽然index和all都是读全表,但index是从索引中读的,而all是从硬盘中读的。
  • ALL:即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。

5、possible_keys

  • 查询条件字段涉及到的索引,可能没有使用。
  • explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。
  • 如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果

6、key

实际使用的索引。如果为 NULL,则没有使用索引。
如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使forceindex、ignore index。

7、key_len

表示索引中使用的字节数,查询中使用的索引的长度(最大可能长度),并非实际使用长度,理论上长度越短越好。key_len 是根据表定义计算而得的,不是通过表内检索出的。

8、ref

显示索引的哪一列被使用了,如果可能的话,是一个常量 const。

9、rows

根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数。注意这个不是结果集里的行数, 数值越低越好。

10、fitered

显示了通过条件过滤出的行数的百分比估计值。

10、Extra

  • Distinct: MySQL 发现第 1 个匹配行后,停止为当前的行组合搜索更多的行。
  • Not exists:MySQL 能够对查询进行 LEFT JOIN 优化,发现 1 个匹配 LEFT JOIN 标准的行后,不再为前面的的行组合在该表内检查更多的行。
  • range checked for each record (index map: #):MySQL 没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
  • Using filesort: 说明mysql会对数据使用**一个外部的索引排序,而不是按照表内的索引顺序进行读取。Mysql中无法利用索引完成的排序操作称为“文件排序”**这种情况下一般也是要考虑使用索引来优化的。
  • Using index: 表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率不错!如果同时出现了using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作.
  • Using temporary:为了解决查询,MySQL 需要创建一个临时表来容纳结果。使用了临时表保存中间结果。常见于排序order by和分组查询group by。Using filesort和Using temporary都是不太好的结果,会影响性能。
  • Using where: 表示使用了where过滤。
  • Using sort_union(…), Using union(…), Using intersect(…): 这 些 函 数 说 明 如 何 为index_merge 联接类型合并索引扫描。
  • Using index for group-by:类似于访问表的 Using index 方式,Using index for group-by 表示MySQL发现了一个索引,可以用来查 询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。

3、索引失效详解

3.1、索引失效情况

七字诀:模型数空运最快

  • 模:模糊查询LIKE以%开头
  • 型:数据类型错误
  • 数:对索引字段使用内部函数
  • 空:索引列是NULL
  • 运:索引列进行四则运算
  • 最:复合索引不按索引列最左开始查找
  • 快:全表查找预计比索引更快
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQLEXPLAIN语句用于分析和优化查询语句的执行计划。通过执行EXPLAIN语句,你可以了解MySQL是如何处理你的查询,包括表的访问顺序、使用的索引、连接方式等。 下面是使用EXPLAIN语句来优化SQL查询的步骤: 1. 确定要优化的查询语句。可以使用SELECT语句来查询数据,然后在该语句前加上EXPLAIN关键字。例如:EXPLAIN SELECT * FROM table_name WHERE condition; 2. 执行EXPLAIN语句,并查看结果。执行EXPLAIN后,MySQL会返回一张表格,其中包含了查询的执行计划信息。这些信息可以帮助你分析查询的性能瓶颈。 3. 分析执行计划信息。在执行计划信息表格中,你可以关注以下几个重要的列: - id: 查询的唯一标识符。多表查询时,每个表都有一个唯一标识符。 - select_type: 查询类型。包括简单查询、联接查询、子查询等。 - table: 查询涉及的表名。 - type: 表示MySQL访问表的方式,常见的有ALL、index、range、ref等。 - possible_keys: 表示可能使用的索引。 - key: 实际使用的索引。 - rows: 估计扫描的行数。 - Extra: 额外的信息,如是否使用了临时表、是否使用了文件排序等。 4. 根据执行计划信息来进行优化。根据查询的复杂性和性能要求,你可以采取以下一些优化措施: - 确保表中的列上有适当的索引。 - 使用JOIN语句时,确保连接条件上有索引。 - 避免在查询中使用通配符(如SELECT *)。 - 尽量减少子查询的使用。 - 优化WHERE条件,尽量避免使用OR、NOT等复杂的逻辑判断。 - 使用合适的数据类型,避免不必要的数据类型转换。 通过不断地执行EXPLAIN语句,分析执行计划信息,并针对性地进行优化,你可以提高查询的性能并减少数据库的负载。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值