MySQL: 使用explain 优化查询性能
来源:SegmentFault
时间:2023-01-22 18:24:20 492浏览 收藏
编程并不是一个机械性的工作,而是需要有思考,有创新的工作,语法是固定的,但解决问题的思路则是依靠人的思维,这就需要我们坚持学习和更新自己的知识。今天golang学习网就整理分享《MySQL: 使用explain 优化查询性能》,文章讲解的知识点主要包括MySQL、explain,如果你对数据库方面的知识点感兴趣,就不要错过golang学习网,在这可以对大家的知识积累有所帮助,助力开发能力的提升。
Explain 介绍
为了优化MySQL的SQL语句的执行性能,MySQL提供了explain关键字用于查看SQL的执行计划。
格式如下:
{EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] {EXPLAIN | DESCRIBE | DESC} [explain_type] {explainable_stmt | FOR CONNECTION connection_id} explain_type: { EXTENDED | PARTITIONS | FORMAT = format_name } format_name: { TRADITIONAL | JSON } explainable_stmt: { SELECT statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement }
DESCRIBE和EXPLAIN语句是同义词。实际上,DESCRIBE关键字更常用于获取有关表结构的信息,而EXPLAIN用于获取查询执行计划(即,解释MySQL将如何执行查询)。
从上面的EXPLAIN的用法可以看出:
- EXPLAIN 可以与 SELECT, DELETE, INSERT, REPLACE 和 UPDATE 一起使用,用于查询相应SQL的执行计划。
- 当EXPLAIN与可解释语句(explainable statement)一起使用时,MySQL显示来自优化器的关于语句执行计划的信息。也就是说,MySQL解释了它将如何处理该语句,包括有关如何联接表以及以何种顺序联接表的信息。
- 当EXPLAIN与
FOR CONNECTION connect_id
而不是可解释语句一起使用时,它将显示在命名连接中执行的语句的执行计划。 - 对于SELECT语句,EXPLAIN可以使用SHOW WARNINGS 语句显示的其他额外的执行计划信息。
- EXPLAIN对于检查涉及分区表的查询很有用。
- FORMAT选项可用于选择输出格式。TRADITIONAL以表格格式显示输出,默认为TRADITIONAL,JSON格式以JSON格式显示信息。
在EXPLAIN的帮助下,可以看到应该在哪里向表添加索引,以便通过使用索引查找使语句执行得更快,还可以使用EXPLAIN检查优化器是否以最佳顺序连接表。
当EXPLAIN与SELECT语句一起使用时,EXPLAIN的结果以表格的格式显示输出,每个行表示一张表。MYSQL使用循环内嵌的方法解析所有的表的连接,也就意味着MYSQL会先读取第一张表的第一行,然后在第二张表中查找匹配的行,然后是第三张表等。当所有的表格都处理完成之后,MySQL输出所选列并回溯所有表,直到找到一个表,其中有更多匹配行。从该表中读取下一行,并继续处理下一个表。
Explain 的输出
EXPLAIN中的每个输出行提供关于一个表的信息。
EXPLAIN的输出如下(第二列为FORMAT=JSON时的输出):
Column | JSON Name | Meaning |
---|---|---|
id | select_id | The SELECT identifier |
select_type | None | The SELECT type |
table | table_name | The table for the output row |
partitions | partitions | The matching partitions |
type | access_type | The join type |
possible_keys | possible_keys | The possible indexes to choose |
key | key | The index actually chosen |
key_len | key_length | The length of the chosen key |
ref | ref | The columns compared to the index |
rows | rows | Estimate of rows to be examined |
filtered | filtered | Percentage of rows filtered by table condition |
Extra | None | Additional information |
下面对上面的每一列逐一说明:
id : 这是查询中SELECT的序列号。如果该行指的是其他行的UNION结果,则该值可以为NULL。在这种情况下,table 列显示一个类似
explain select * from small_note.small_note_detail where id = 5 union select * from small_note.small_note_detail where id = 6;
结果如下:
select_type: select_type的取值如下:
select_type Value | Meaning |
---|---|
SIMPLE | 简单查询,没有使用UNION和子查询 |
PRIMARY | 最外层的SELECT语句 |
UNION | UNION中第二个或者更后的SELECT语句 |
DEPENDENT UNION | UNION中的第二个或以后的SELECT语句,依赖于外部查询 |
UNION RESULT | UNION的结果,因为它不需要参与查询,所以id字段为NULL |
SUBQUERY | 除了from字句中包含的子查询外,其他地方出现的子查询都可能是SUBQUERY类型 |
DEPENDENT SUBQUERY | 子查询中的第一个SELECT语句, 依赖于外部查询, 对于上下文中变量的每一组不同值,子查询只重新计算一次 |
DERIVED | FROM语句中出现的子查询,也叫做派生表, 当FROM语句中包含多个SELECT语句时,第一个SELECT语句的select_type也可能为DERIVED |
MATERIALIZED | 物化的字查询 |
UNCACHEABLE SUBQUERY | 子查询的结果不能缓存下来,对于外部查询的每一行都需要重新计算 |
UNCACHEABLE UNION | UNION中的第二个或以后的SELECT语句属于UNCACHEABLE SUBQUERY |
DEPENDENT SUBQUERY与UNCACHEABLE SUBQUERY不同。对于DEPENDENT SUBQUERY,对于外部上下文中变量的每一组不同值,子查询只重新计算一次。对于UNCACHEABLE SUBQUERY,将为外部上下文的每一行重新计算子查询。
非SELECT语句的select_type为语句的type, 比如对于DELETE语句而言,其select type 就是DELETE。
table: 表的名称。除了可以是表的名称,这也可以是以下值之一。
partitions : 查询匹配的分区,对于非分区表,该值为NULL。
type:关联类型,决定通过什么方式找到每一行数据。以下按照速度由快到慢。
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL。
- system,表中只有一行记录,相当于系统表;
- const,该表最多有一个匹配行,在查询开始时读取。因为只有一行,所以优化器的其余部分可以将此行中列的值视为常量。常量表非常快,因为它们只读取一次。将主键或唯一索引的所有部分与常量值进行比较时,type将是const。
- eq_ref,读取本表中和关联表表中的每行组合成的一行,即只返回一条数据。除了system和const类型之外,这是最好的联接类型。当联接使用索引的所有部分,并且索引是主键或唯一的非空索引时,type为eq_ref。
- ref,将从此表中读取具有匹配索引值的所有行。如果联接仅使用键的最左侧前缀,或者键不是主键或唯一索引(换句话说,如果联接无法基于键值选择单行),则使用ref。如果使用的键只匹配几行,则这是一种良好的联接类型。ref可用于使用=或运算符进行比较的索引列。
- fulltext, 使用FULLTEXT索引
- ref_or_null, 和ref类似,但是还要进行一次查询找到NULL的数据。
- index_merge, 对于单表查询(无法跨表合并)用到了多个索引的情况,每个索引都可能返回一个结果,Mysql会对结果进行取并集、交集,这就是索引合并了。
- unique_subquery, 对于in的子查询中使用了唯一索引,有的时候使用unique_subquery而不是eq_ref
- index_subquery, 和unique_subquery类似,只是针对的是非唯一索引。
- range,只检索给定范围的行,使用一个索引来选择行,一般用于between、;
- index,只遍历索引树;
- all,全表扫描;
possible_keys: 表示MySQL可以从中选择查找此表中的行的索引。请注意,此列完全独立于EXPLAIN输出中显示的表格顺序。这意味着possible_keys中的一些键在实际生成的表顺序中可能不可用。
key: 表示MySQL实际决定使用的键(索引)。如果MySQL决定使用possible_keys中的某个索引来查找行,则该索引将作为键值列出。key也可能是possible_keys中不存在的索引,如果所有possible_keys都不适合查找行,但查询选择的所有列都是其他索引的列,则可能发生这种情况。也就是说,命名索引覆盖选定的列,因此尽管它不用于确定要检索的行,但索引扫描比数据行扫描更有效。
key_len: key_len列表示MySQL决定使用的key的长度(字节),char为4个字节,允许为NULL需要额外一个字节,不定长还需要额外2个字节存储长度。如果key列表示NULL,则key_len列也表示NULL。
ref: 显示该表的索引字段关联了哪张表的哪个字段;
rows: 表示MySQL认为执行查询必须检查的行数。
filtered:返回结果的行数占读取行数的百分比,值越大越好;
extra:包含不适合在其他列中显示但十分重要的额外信息。常见的值如下:
- using filesort,MySQL会对数据使用一个外部索引排序,而不是按照表内索引顺序进行读取,若出现改值,则应优化SQL语句;
- using temporary,使用临时表缓存中间结果,比如,MySQL在对查询结果排序时使用临时表,常见于order by和group by,若出现该值,则应优化SQL;
- using index,仅使用索引树中的信息从表中检索列信息,而无需进行额外的查找以读取实际行。 当查询仅使用属于单个索引的列时,可以使用此策略。表示select操作使用了覆盖索引,避免了访问表的数据行;
- Using index condition, 使用索引下推,索引下推简单来说就是加上了条件筛选,需要回表,但是减少了回表的操作。
- using where,where子句用于限制哪一行;
- using join buffer,使用连接缓存;
- distinct,发现第一个匹配后,停止为当前的行组合搜索更多的行;
今天关于《MySQL: 使用explain 优化查询性能》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
-
499 收藏
-
244 收藏
-
235 收藏
-
157 收藏
-
101 收藏
-
176 收藏
-
368 收藏
-
475 收藏
-
266 收藏
-
273 收藏
-
283 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 虚幻的丝袜
- 很棒,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢大佬分享文章内容!
- 2023-06-21 19:20:46
-
- 闪闪的狗
- 这篇技术文章真是及时雨啊,博主加油!
- 2023-05-21 08:37:16
-
- 谨慎的酒窝
- 这篇技术文章真是及时雨啊,好细啊,感谢大佬分享,码住,关注大佬了!希望大佬能多写数据库相关的文章。
- 2023-04-19 00:39:45
-
- 激昂的老师
- 这篇技术文章真及时,楼主加油!
- 2023-04-11 12:36:47
-
- 端庄的小蚂蚁
- 这篇技术文章真是及时雨啊,太细致了,很有用,码起来,关注师傅了!希望师傅能多写数据库相关的文章。
- 2023-03-10 04:45:21
-
- 欣慰的鼠标
- 这篇技术文章真及时,很详细,太给力了,已加入收藏夹了,关注博主了!希望博主能多写数据库相关的文章。
- 2023-02-25 14:45:24
-
- 眯眯眼的钥匙
- 细节满满,mark,感谢师傅的这篇博文,我会继续支持!
- 2023-02-14 21:45:59
-
- 耍酷的西牛
- 很详细,码起来,感谢up主的这篇博文,我会继续支持!
- 2023-02-09 16:19:29
-
- 清脆的板凳
- 这篇技术贴出现的刚刚好,好细啊,太给力了,收藏了,关注作者了!希望作者能多写数据库相关的文章。
- 2023-02-08 16:05:12
-
- 甜美的小土豆
- 很好,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者大大分享技术文章!
- 2023-02-06 21:18:13
-
- 雪白的雪糕
- 很好,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢师傅分享文章内容!
- 2023-02-01 17:47:30
-
- 俊逸的火龙果
- 写的不错,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢老哥分享文章!
- 2023-01-29 03:29:17
-
- 靓丽的麦片
- 太全面了,收藏了,感谢大佬的这篇博文,我会继续支持!
- 2023-01-25 01:05:44