sql性能分析之EXPLAIN

EXPLAIN提供了有关如何执行SQL语句的信息,用于select,delete,insert,update,replace等语句中。在select语句中使用EXPLAIN将返回一行信息(每个表对应一行,包含临时表),按照处理语句时的顺序显示。存在表连接时,使用循环嵌套的方式解析所有连接,也就是说从第一个表中读取一行然后在第二个表中匹配所有符合条件的行,然后再在第三个表……。当所有的表处理完后,输出选中的列并且返回表清单直到找到一个有更多匹配行的表。从该表读入一行并继续处理下一个表。EXPLAIN的输出包含分区信息,对于select语句和DESCRIBE相似(通常情况下DESCRIBE用于获取表结构的信息,而EXPLAIN用于语句的执行计划,即解释如何执行查询)。

EXPLAIN输出列

每行输出代表一个表的相关信息,包含以下字段(JSON 名称为使用FORMAT=JSON时的key)

Column JSON名称 说明
id select_id SELECT标识
select_type SELECT类型
table table_name 输出行所应用的表
partitions partitions 匹配分区
type access_type 连接类型
possible_keys possible_keys 可能选择的索引
key key 实际选择的索引
key_len key_length key的长度
ref ref The columns compared to the index
rows rows 估计要扫描的检查的行数
filtered filtered 按条件过滤行的百分比
Extra 附加信息
  • id
    SELECT识别符,SELECT的查询序列号。
  • select_type
    select类型可以是以下值:
select_type 值 JSON 名称 说明
SIMPLE 简单select语句 (未使用子查询和union)
PRIMARY 最外层select
UNION union语句中的第二个往后的select语句
DEPENDENT UNION dependent (true) union语句中的第二个往后的select语句, 取决于外层查询
UNION RESULT union_result 一个union的结果
SUBQUERY 第一个子查询
DEPENDENT SUBQUERY dependent (true) 第一个子查询,取决于外层查询
DERIVED 派生表 (from 子句中的子查询)
MATERIALIZED materialized_from_subquery 物化子查询(子查询通常缓存在内存或临时表里)
UNCACHEABLE SUBQUERY cacheable (false) 不能将子查询结果缓存并且必须对外部查询的每一行重新评估
UNCACHEABLE UNION cacheable (false) 第二个往后的unioon不可缓存子查询(见UNCACHEABLE SUBQUERY)

注:在查询缓存中子查询的缓存行和查询结果的缓存不同,子查询缓存发生在查询期间,而查询缓存在查询完成后才进行存储结果。具体查询如何缓存,请参照:https://dev.mysql.com/doc/refman/5.7/en/query-cache-operation.html

  • table
    引用表的名称。如果使用别名,这里将显示别名。也可以是以下几种情况:
    <unionM,N>,<derivedN>,subqueryN>。M和N为返回行的id

  • partitions
    记录由查询匹配的分区。该值为NULL表示用于非分区表。(关于表分区可用show create table查看)

  • type
    连接类型。依次从好到差:

  • system
    表中只有一行(系统表)。是const连接类型的特殊情况 。

  • const
    使用唯一索引或者主键,返回记录一定只有一行,通常是const。
    在下面的查询中,tbl_name可以用于const表
    SELECT * from tbl_name WHERE primary_key = 1
    SELECT * from tbl_name WHERE primary_key_part1 = 1 AND primary_key_part2 = 2

  • eq_ref
    对于每个来自于前表的行组合,从该表中读取一行。它使用一个索引连接并且索引是UNIQUE或PRIMARY KEY,这可能是除了system和const类型外最好的连接类型。eq_ref可以是使用 = 操作符比较索引列,比较值可以是常量或一个列的表达式
    在下面的查询中,使用eq_ref连接进行处理
    SELECT * FROM ref_table,other_table WHERE ref_table.key_column = other_table.column
    SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1 = other_table.column AND ref_table.key_column_part2 = 1

  • ref
    对于每个来自于前表的行组合,读取所有匹配索引值的行。若索引不是UNIQUE或PRIMARY KEY(也就是说连接不能返回单行的话)则类型是ref。如果匹配少量的行,该连接类型还是不错的。
    在下面的查询中,使用ref连接进行处理
    SELECT * FROM ref_table WHERE key_column = expr
    SELECT * FROM ref_table,other_table WHERE ref_table.key_column = other_table.column
    SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1 = other_table.column AND ref_table.key_column_part2 = 1

  • fulltext
    全文索引检索,要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,优先选择使用全文索引。

  • ref_or_null
    该联接类型同ref,只是添加了专门包含NULL值的行。
    在下面的查询中,使用ref_or_null联接来处理ref_tables:
    SELECT * FROM ref_table WHERE key_column = expr OR key_column IS NULL

  • index_merge
    使用两个及以上的索引合并查询,常用or或and
    在下面的查询中,使用ref_or_null联接来处理ref_tables:
    SELECT * FROM ref_table WHERE key_column1 = expr1 and key_column2 = expr2

  • unique_subquery
    这个类型使用in的子查询替换eq_ref
    value IN (SELECT primary_key FROM single_table WHERE some_expr)
    unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高

  • index_subquery
    该联接类型类似于unique_subquery。适用于子查询包含非唯一索引的情况。
    value IN (SELECT key_column FROM single_table WHERE some_expr)

  • range
    索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中。

  • index
    该连接类型类似于ALL,除了索引树被扫描。通常有两种方式:
    1:如果索引是用于满足表中所需的所有数据时的覆盖索引,则仅扫描索引树。这种情况下,Extra中包含 Using index。因为索 引比表数据更小,所以这种情况通常比All更快。
    2:使用索引读取执行全表扫描,按索引顺序查找数据行。Extra中不包含 Using index。
    当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

  • ALL
    全表扫描然后过滤,通常性能很差。

  • possible_keys
    表示可以选择哪些索引来查找此表中的行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看它是否引用某些适合使用索引的列来提高你的查询性能。这样,创建一个合适的索引并且再次用EXPLAIN检查查询

  • key
    实际使用的索引,如果没有选择索引则为NULL

  • key_len
    索引长度。如果索引是NULL,则长度为NULL

  • ref
    ref列显示使用哪个列或常数与索引匹配行。

  • rows
    执行查询时必须检查的行数。

  • filtered
    该filtered列指示将由表条件过滤的表行的估计百分比。也就是说,rows 显示估计的行数, rows× filtered/ 100显示与先前表相连接的行数。

  • Extra
    包含有关如何解析查询的其他信息。参照https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain_extra

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容