mysql explain讲解

本文咱们主要介绍了MySQL性能分析以及explain的使用,包括:组合索引、慢查询分析、MYISAM和INNODB的锁定、MYSQL的事务配置项等,但愿可以对您有所帮助。mysql

1.使用explain语句去查看分析结果 
如explain select * from test1 where id=1;会出现:id selecttype table type possible_keys key key_len ref rows extra各列。算法


其中, 
type=const表示经过索引一次就找到了; 
key=primary的话,表示使用了主键; 
type=all,表示为全表扫描; 
key=null表示没用到索引。sql

type=ref,由于这时认为是多个匹配行,在联合查询中,通常为REF。缓存

MySQL 查询优化器是如何工做的
MySQL 查询优化器有几个目标,可是其中最主要的目标是尽量地使用索引,而且使用最严格的索引来消除尽量多的数据行。最终目标是提交 SELECT 语句查找数据行,而不是排除数据行。优化器试图排除数据行的缘由在于它排除数据行的速度越快,那么找到与条件匹配的数据行也就越快。若是可以首先进行最严格的测试,查询就能够执行地更快。
EXPLAIN 的每一个输出行提供一个表的相关信息,而且每一个行包括下面的列: 安全

说明
id MySQL Query Optimizer 选定的执行计划中查询的序列号。表示查询中执行 select 子句或操做表的顺序,id 值越大优先级越高,越先被执行。id 相同,执行顺序由上至下。

 

select_type 查询类型 说明
SIMPLE 简单的 select 查询,不使用 union 及子查询
PRIMARY 最外层的 select 查询
UNION UNION 中的第二个或随后的 select 查询,不 依赖于外部查询的结果集
DEPENDENT UNION UNION 中的第二个或随后的 select 查询,依 赖于外部查询的结果集
SUBQUERY 子查询中的第一个 select 查询,不依赖于外 部查询的结果集
DEPENDENT SUBQUERY 子查询中的第一个 select 查询,依赖于外部 查询的结果集
DERIVED 用于 from 子句里有子查询的状况。 MySQL 会 递归执行这些子查询, 把结果放在临时表里。
UNCACHEABLE SUBQUERY 结果集不能被缓存的子查询,必须从新为外 层查询的每一行进行评估。
UNCACHEABLE UNION UNION 中的第二个或随后的 select 查询,属 于不可缓存的子查询

 

说明
table 输出行所引用的表

 

type 重要的项,显示链接使用的类型,按最 优到最差的类型排序 说明
system 表仅有一行(=系统表)。这是 const 链接类型的一个特例。
const const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System。
eq_ref const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System。
ref 链接不能基于关键字选择单个行,可能查找 到多个符合条件的行。 叫作 ref 是由于索引要 跟某个参考值相比较。这个参考值或者是一 个常数,或者是来自一个表里的多表查询的 结果值。
ref_or_null 如同 ref, 可是 MySQL 必须在初次查找的结果 里找出 null 条目,而后进行二次查找。
index_merge 说明索引合并优化被使用了。
unique_subquery 在某些 IN 查询中使用此种类型,而不是常规的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr)
index_subquery 在 某 些 IN 查 询 中 使 用 此 种 类 型 , 与 unique_subquery 相似,可是查询的是非惟一 性索引: value IN (SELECT key_column FROM single_table WHERE some_expr)
range 只检索给定范围的行,使用一个索引来选择 行。key 列显示使用了哪一个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操做符,用常量比较关键字列时,可 以使用 range。
index 全表扫描,只是扫描表的时候按照索引次序 进行而不是行。主要优势就是避免了排序, 可是开销仍然很是大。
all 最坏的状况,从头至尾全表扫描。


 

说明
possible_keys 指出 MySQL 能在该表中使用哪些索引有助于 查询。若是为空,说明没有可用的索引。

 

说明
key MySQL 实际从 possible_key 选择使用的索引。 若是为 NULL,则没有使用索引。不多的状况 下,MYSQL 会选择优化不足的索引。这种情 况下,能够在 SELECT 语句中使用 USE INDEX (indexname)来强制使用一个索引或者用 IGNORE INDEX(indexname)来强制 MYSQL 忽略索引

 

说明
key_len 使用的索引的长度。在不损失精确性的状况 下,长度越短越好。

 

说明
ref 显示索引的哪一列被使用了

 

说明
rows MYSQL 认为必须检查的用来返回请求数据的行数

 

说明
rows MYSQL 认为必须检查的用来返回请求数据的行数

 

extra 中出现如下 2 项意味着 MYSQL 根本不能使用索引,效率会受到重大影响。应尽量对此进行优化。服务器

extra 项 说明
Using filesort 表示 MySQL 会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中没法利用索引完成的排序操做称为“文件排序”
Using temporary 表示 MySQL 在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。

2.MYSQL中的组合索引 
假设表有id,key1,key2,key3,把三者造成一个组合索引,则如: 
复制代码 代码以下:函数

  1. where key1=....   
  2. where key1=1 and key2=2   
  3. where key1=3 and key2=3 and key3=2   

根据最左前缀原则,这些都是可使用索引的,如from test where key1=1 order by key3,用explain分析的话,只用到了normal_key索引,但只对where子句起做用,然后面的order by须要排序。性能

 

3.使用慢查询分析(实用)
在my.ini中: 
long_query_time=1 
log-slow-queries=d:\mysql5\logs\mysqlslow.log 
把超过1秒的记录在慢查询日志中 
能够用mysqlsla来分析之。也能够在mysqlreport中,有如 
DMS分别分析了select ,update,insert,delete,replace等所占的百分比测试


4.MYISAM和INNODB的锁定 
myisam中,注意是表锁来的,好比在多个UPDATE操做后,再SELECT时,会发现SELECT操做被锁定了,必须等全部UPDATE操做完毕后,再能SELECT
innodb的话则不一样了,用的是行锁,不存在上面问题。 优化

 

5.MYSQL的事务配置项 
innodb_flush_log_at_trx_commit=1 
表示事务提交时当即把事务日志flush写入磁盘,同时数据和索引也更新,很费性能。
innodb_flush_log_at_trx_commit=0 
事务提交时,不当即把事务日志写入磁盘,每隔1秒写一次,MySQL挂了可能会丢失事务的数据。
innodb_flush_log_at_trx_commit=2 ,在整个操做系统 挂了时才可能丢数据,通常不会丢失超过1-2秒的更新。
事务提交时,当即写入磁盘文件(这里只是写入到系统内核缓冲区,但不当即刷新到磁盘,而是每隔1秒刷新到磁盘,同时更新数据和索引),这种方案是否是性价比好一些,固然如何配置,决定于你对系统数据安全性的要求。


explain用法详解
EXPLAIN tbl_name或:EXPLAIN [EXTENDED] SELECT select_options 
前者能够得出一个表的字段结构等等,后者主要是给出相关的一些索引信息,而今天要讲述的重点是后者。 
举例

  1. mysql> explain select * from event;   
  2. +—-+————-+——-+——+—————+——+———+——+——+——-+   
  3. | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |   
  4. +—-+————-+——-+——+—————+——+———+——+——+——-+   
  5. | 1 | SIMPLE | event | ALL | NULL | NULL | NULL | NULL | 13 | |   
  6. +—-+————-+——-+——+—————+——+———+——+——+——-+   
  7. 1 row in set (0.00 sec)   

各个属性的含义


id :select查询的序列号


select_type:select查询的类型,主要是区别普通查询和联合查询、子查询之类的复杂查询。

a.SIMPLE:查询中不包含子查询或者UNION

b.查询中若包含任何复杂的子部分,最外层查询则被标记为:PRIMARY

c.在SELECT或WHERE列表中包含了子查询,该子查询被标记为:SUBQUERY

d.在FROM列表中包含的子查询被标记为:DERIVED(衍生)

e.若第二个SELECT出如今UNION以后,则被标记为UNION;若UNION包含在 FROM子句的子查询中,外层SELECT将被标记为:DERIVED

f.从UNION表获取结果的SELECT被标记为:UNION RESULT


table :输出的行所引用的表。


type :联合查询所使用的类型,表示MySQL在表中找到所需行的方式,又称“访问类型”。


type显示的是访问类型,是较为重要的一个指标,结果值从好到坏依次是: 
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL ,通常来讲,得保证查询至少达到range级别,最好能达到ref。

ALL: 扫描全表
index: 扫描所有索引树
range: 扫描部分索引,索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询
ref: 非惟一性索引扫描,返回匹配某个单独值的全部行。常见于使用非惟一索引即惟一索引的非惟一前缀进行的查找

eq_ref:惟一性索引扫描,对于每一个索引键,表中只有一条记录与之匹配。常见于主键或惟一索引扫描
const, system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。system是const类型的特例,当查询的表只有一行的状况下, 使用system。
NULL: MySQL在优化过程当中分解语句,执行时甚至不用访问表或索引。

以下所示:

 

possible_keys:指出MySQL能使用哪一个索引在该表中找到行。查询涉及到的字段上若存在索引,则该索引将被列出,但不必定被查询使用。若是是空的,没有相关的索引。这时要提升性能,可经过检验WHERE子句,看是否引用某些字段,或者检查字段不是适合索引。 
 

key :显示MySQL实际决定使用的键。若是没有索引被选择,键是NULL。

 

key_len:显示MySQL决定使用的键长度。表示索引中使用的字节数,可经过该列计算查询中使用的索引的长度。若是键是NULL,长度就是NULL。文档提示特别注意这个值能够得出一个多重主键里mysql实际使用了哪一部分。

 注:key_len显示的值为索引字段的最大可能长度,并不是实际使用长度,即key_len是根据表定义计算而得,不是经过表内检索出的。

ref:显示哪一个字段或常数与key一块儿被使用。

 

rows:这个数表示mysql要遍历多少数据才能找到,表示MySQL根据表统计信息及索引选用状况,估算的找到所需的记录所须要读取的行数,在innodb上多是不许确的。

 

Extra:包含不适合在其余列中显示但十分重要的额外信息。

Only index,这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。 


using where是使用上了where限制,表示MySQL服务器在存储引擎受到记录后进行“后过滤”(Post-filter),若是查询未能使用索引,Using where的做用只是提醒咱们MySQL将用where子句来过滤结果集。


impossible where 表示用不着where,通常就是没查出来啥。 


Using filesort(MySQL中没法利用索引完成的排序操做称为“文件排序”)当咱们试图对一个没有索引的字段进行排序时,就是filesoft。它跟文件没有任何关系,其实是内部的一个快速排序。 

 

Using temporary(表示MySQL须要使用临时表来存储结果集,常见于排序和分组查询),使用filesort和temporary的话会很吃力,WHERE和ORDER BY的索引常常没法兼顾,若是按照WHERE来肯定索引,那么在ORDER BY时,就必然会引发Using filesort,这就要看是先过滤再排序划算,仍是先排序再过滤划算。

 

最后,再看一个查询计划的例子:

第一行:id列为1,表示第一个select,select_type列的primary表示该查询为外层查询,table列被标记为<derived3>,表示查询结果来自一个衍生表,其中3表明该查询衍生自第三个select查询,即id为3的select。[select d1.name......]
第二行:id为3,表示该查询的执行次序为2(4→3),是整个查询中第三个select的一部分。因查询包含在from中,因此为derived。[select id,name from t1 where other_column='']
第三行:select列表中的子查询,select_type为subquery,为整个查询中的第二个select。[select id from t3]
第四行:select_type为union,说明第四个select是union里的第二个select,最早执行。[select name,id from t2]
第五行:表明从union的临时表中读取行的阶段,table列的<union1,4>表示用第一个和第四个select的结果进行union操做。[两个结果union操做]

 

关于MySQL执行计划的局限性:

EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响状况
EXPLAIN不考虑各类Cache
EXPLAIN不能显示MySQL在执行查询时所做的优化工做
部分统计信息是估算的,并不是精确值
EXPALIN只能解释SELECT操做,其余操做要重写为SELECT后查看。

 

备注:

filesort是经过相应的排序算法,将取得的数据在内存中进行排序。


MySQL须要将数据在内存中进行排序,所使用的内存区域也就是咱们经过sort_buffer_size 系统变量所设置的排序区。这个排序区是每一个Thread 独享的,因此说可能在同一时刻在MySQL 中可能存在多个 sort buffer 内存区域。


在MySQL中filesort 的实现算法其实是有两种:

双路排序:是首先根据相应的条件取出相应的排序字段和能够直接定位行数据的行指针信息,而后在sort buffer 中进行排序。
单路排序:是一次性取出知足条件行的全部字段,而后在sort buffer中进行排序。


在MySQL4.1版本以前只有第一种排序算法双路排序,第二种算法是从MySQL4.1开始的改进算法,主要目的是为了减小第一次算法中须要两次访问表数据的IO操做,将两次变成了一次,但相应也会耗用更多的sortbuffer 空间。固然,MySQL4.1开始的之后全部版本同时也支持第一种算法。
MySQL主要经过比较咱们所设定的系统参数 max_length_for_sort_data的大小和Query 语句所取出的字段类型大小总和来断定须要使用哪种排序算法。若是 max_length_for_sort_data更大,则使用第二种优化后的算法,反之使用第一种算法。因此若是但愿 ORDER BY 操做的效率尽量的高,必定要注意max_length_for_sort_data 参数的设置。若是filesort过程当中,因为排序缓存的大小不够大,那么就可能会致使临时表的使用。 max_length_for_sort_data的默认值是1024。

相关文章
相关标签/搜索