【mysql】分析mysql执行计划

使用EXPLAIN优化查询

EXPLAIN后可接 SELECT, DELETE, INSERT, REPLACE,和 UPDATE语句。如下:

explain 
select DISTINCT r.STAFF_IDS, d.SPLITLIST_ID, d.SPLITLIST_NAME, d.LIST_ID, d.OWNED_CITY, d.OWNED_CHANNEL, d.STORAGE_PATH, d.REMARK, m.PUBLISHER_TIME, m.EXP_TIME, m.LIST_STATUS, o.DOWNLOAD_STATUS, m.CATEGORY, m.LIST_ID, m.belong_date 
from rpt_list m 
left join rpt_split_list d on d.LIST_ID = m.LIST_ID 
left join rpt_list_staff_rel r ON d.SPLITLIST_ID=r.list_id 
left join rpt_listexp_log o on d.SPLITLIST_ID = o.SPLITLIST_ID 
WHERE m.LIST_STATUS = '5' 
and ((m.category in ('jkqd', 'scbqd', 'zqkhb', 'cljy', '2to4') and r.staff_ids IS NULL  
and d.OWNED_CITY in ('沈阳','48元档位') ) 
or (r.STAFF_IDS in ( '822') and m.category in ('staff'))) 
order by publisher_time desc limit 0 , 10 ;

查询结果如下:
执行计划结果

EXPLAIN输出格式

EXPLAIN输出列

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 所选键的长度
ref ref 列与索引进行比较
rows rows 估计要检查的行
filtered filtered 按表条件过滤的行的百分比
Extra 没有 附加信息

id

包含一组数字,表示查询中执行select子句或操作表的顺序
id相同,执行顺序由上至下,否则id值越大(通常子查询会产生)优先级越高,越先被执行
id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行

select_type

select_type值 含义
SIMPLE 简单SELECT(不使用 UNION或子查询)
PRIMARY Outermost SELECT 最外层select
UNION Second or later SELECT statement in a UNION
DEPENDENT UNION Second or later SELECT statement in a UNION, dependent on outer query
UNION RESULT Result of a UNION.
SUBQUERY First SELECT in subquery
DEPENDENT SUBQUERY First SELECT in subquery, dependent on outer query(通常为相关子查询)
DERIVED 派生表 Derived table SELECT (subquery in FROM clause)
MATERIALIZED 物化子查询 Materialized subquery
UNCACHEABLE SUBQUERY 无法缓存结果的子查询,必须为外部查询的每一行重新计算 A subquery for which the result cannot be cached and must be reevaluated
UNCACHEABLE UNION for each row of the outer query

table

输出行引用的表的名称。

partitions

查询将匹配记录的分区。仅当使用PARTITIONS关键字时,才会显示此列 。该值适用NULL于非分区表。

type

连接类型。以下列表描述了从最佳类型到最差类型的连接类型:

system

该表只有一行(=系统表)。这是const连接类型的特例 。

const

该表最多只有一个匹配行,在查询开头读取。因为只有一行,所以优化器的其余部分可以将此行中列的值视为常量。 const表非常快,因为它们只读一次。

const将a PRIMARY KEY或 UNIQUE索引的所有部分与常量值进行比较时使用。在以下查询中,tbl_name可以用作const 表:

eq_ref

对于前面表格中的每个行组合,从该表中读取一行。除了 system和 const类型之外,这是最好的连接类型。当连接使用索引的所有部分且索引是 索引PRIMARY KEY或UNIQUE NOT NULL索引时使用它。

eq_ref可用于使用=运算符进行比较的索引列 。比较值可以是常量,也可以是使用在此表之前读取的表中的列的表达式。

ref

对于前面表中的每个行组合,将从此表中读取具有匹配索引值的所有行。ref如果连接仅使用键的最左前缀或者键不是a PRIMARY KEY或 UNIQUE索引(换句话说,如果连接不能基于键值选择单行),则使用此方法。如果使用的密钥只匹配几行,这是一个很好的连接类型。

ref可以用于使用=or <=> 运算符进行比较的索引列 。

fulltext

全文搜索

ref_or_null

这种连接类型是这样的 ref,但除此之外,MySQL还会对包含NULL值的行进行额外搜索。此连接类型优化最常用于解析子查询。

index_merge

此连接类型表示使用了索引合并优化。在这种情况下,key输出行中的列包含使用的索引列表,并key_len包含所用索引 的最长关键部分的列表。有关更多信息,请参见 第8.2.1.3节“索引合并优化”。

unique_subquery

index_subquery

此连接类型类似于 unique_subquery。

range

仅检索给定范围内的行,使用索引选择行。的key 输出行中的列指示使用哪个索引。将key_len包含已使用的时间最长的关键部分。该ref列 NULL适用于此类型。

range当一个键柱使用任何的相比于恒定可使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE,或 IN()

index

该index联接类型是一样的 ALL,只是索引树被扫描。这有两种方式:

如果索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则仅扫描索引树。在这种情况下,Extra专栏说 Using index。仅索引扫描通常比ALL索引的大小通常小于表数据更快 。

使用索引中的读取执行全表扫描,以按索引顺序查找数据行。 Uses index没有出现在 Extra列中。

当查询仅使用属於单个索引的列时,MySQL可以使用此连接类型。

ALL

对前面表格中的每个行组合进行全表扫描。如果表是第一个未标记的表 const,这通常是不好的,并且在所有其他情况下通常 非常糟糕。通常,您可以ALL通过添加索引来避免 ,这些索引根据以前表中的常量值或列值从表中启用行检索。

possible_keys

该possible_keys列指示MySQL可以从中选择查找此表中的行的索引。请注意,此列完全独立于输出中显示的表的顺序 EXPLAIN。这意味着某些键possible_keys可能无法在生成中使用生成的表顺序。

如果此列是NULL(或在JSON格式的输出中未定义),则没有相关索引。在这种情况下,您可以通过检查WHERE 子句以检查它是否引用适合索引的某些列或列来提高查询性能。如果是,请创建适当的索引并EXPLAIN再次检查查询 。

要查看表有哪些索引,请使用。 SHOW INDEX FROM tbl_name
优化建议

key

该key列指示MySQL实际决定使用的密钥(索引)。如果MySQL决定使用其中一个possible_keys 索引来查找行,那么该索引将被列为键值。

可能key会命名值中不存在的索引 possible_keys。如果没有possible_keys索引适合查找行,则会发生这种情况,但查询选择的所有列都是其他索引的列。也就是说,命名索引覆盖了所选列,因此虽然它不用于确定要检索的行,但索引扫描比数据行扫描更有效。

因为InnoDB,即使查询还选择主键,辅助索引也可能覆盖所选列,因为InnoDB主键值与每个辅助索引一起存储。如果 key是NULL,MySQL没有找到用于更有效地执行查询的索引。

要强制MySQL使用或忽略列出的索引 possible_keys列,使用 FORCE INDEX,USE INDEX或IGNORE INDEX在您的查询。请参见第8.9.3节“索引提示”。

对于MyISAM和NDB 表,运行ANALYZE TABLE有助于优化器选择更好的索引。对于NDB表,这还可以提高分布式下推连接的性能。对于 MyISAM表格,myisamchk --analyze也是如此 ANALYZE TABLE。

key_len

该key_len列指示MySQL决定使用的密钥的长度。该值 key_len使您可以确定MySQL实际使用的多部分密钥的多少部分。如果key列说 NULL,该len_len 列也说NULL。

由于密钥存储格式,对于可能NULL 比列的列,密钥长度更大NOT NULL。在不损失精确性的情况下,长度越短越好。

ref

该ref列显示将哪些列或常量与列中指定的索引进行比较,以 key从表中选择行。

如果值为func,则使用的值是某个函数的结果。要查看哪个函数,请使用 SHOW WARNINGS以下内容 EXPLAIN EXTENDED查看扩展EXPLAIN输出。该函数实际上可能是算术运算符等运算符。

rows

该rows列指示MySQL认为必须检查以执行查询的行数。

对于InnoDB表格,此数字是估算值,可能并不总是准确的。

filtered

该filtered列指示将按表条件过滤的表行的估计百分比。最大值为100,这意味着不会对行进行过滤。值从100开始减少表示过滤量增加。 rows显示检查的估计行数,rows× filtered表示将与下表连接的行数。例如,如果 rows为1000且 filtered为50.00(50%),则使用下表连接的行数为1000×50%= 500.如果使用,则显示此列 EXPLAIN EXTENDED。

Extra

此列包含有关MySQL如何解析查询的其他信息。

Using index condition

通过访问索引元组并首先测试它们以确定是否读取完整的表行来读取表。以这种方式,索引信息用于推迟(“ 下推 ”)读取全表行,除非有必要。
查询优化器功能开关 SELECT @@optimizer_switch
默认情况下启用索引条件下推。可以optimizer_switch通过设置index_condition_pushdown标志来控制 系统变量 :
SET optimizer_switch = ‘index_condition_pushdown=off’;

Using where

使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题。

Using temporary

看到这个的时候,查询需要优化了。这里,mysql需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上。

Using filesort

看到这个的时候,查询就需要优化了。mysql需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行。

Distinct

一旦mysql找到了与行相联合匹配的行,就不再搜索了。

优化建议

  • 表关联字段类型长度完全相同。
  • 将LEFT JOIN其更改为内部联接。
  • 查询条件加索引条件,order by字段在group by中存在。

详见:mysql官方解释文档

上一篇:【mycat】Linux下mycat搭建配置全过程——初学者轻松上手篇
下一篇:【R】linux上安装R及使用shell调用加传参

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章