1.引入
我们通过前几节课,我们对索引有了一定的认识。那么说到底的话,我们还是为了让我们操作的sql性能有一定的提高。那么我们在之前学习MySQL逻辑架构的时候,我们发现MySQL自己是自己带有优化的功能的,如:查询优化器(MySQL Query Optimizer)。那么,下面我们就一起来学习,如何进行SQL的性能分析。
2.MySQL查询优化器简介以及其工作原理
MySQL数据库中有专门负责优化SELECT语句的优化器模块。其主要功能就是通过计算分析系统中收集到的统计信息,为客户端请求的查询操作(即QUERY)提供它认为的最优的执行计划。(这里面的最优执行是数据库自己认为的最优执行,不一定是DBA认为的最优执行)。
当客户端向MySQL请求一条查询语句QUERY,命令解析器模块完成请求分类,区分出是SELECT并转发给MySQL Query Optimizer时,MySQL Query Optimizer首先会对整条Query进行优化,处理掉一些常亮表达式的预算,直接换算成常量值,并对Query中的查询条件进行简化以及转化,如果去掉的是一些无用或者是显而易见的条件,结构调整等,然后分析Query中的Hint信息(如果有),看显示的Hint信息是否可以完全确定该Query的执行计划,如果没有Hint或者是Hint信息还不足以完全确定执行计划,则会读取涉及对象的统计信息,再根据Query进行写相应的计算分析,然后再得出最后的执行计划。
3.MySQL的常见瓶颈
(1).CPU
CPU在饱和的时候一般发生在数据装入内存或者是从磁盘上读取数据的时候。
(2).I/O
磁盘I/O瓶颈发生在装入的数据远大于内存容量的时候
(3).硬件的拼接
top,free,iostat和vmstat来查看系统的性能状态
4.explain使用以及简介
(1).explain是什么,以及有什么作用。
explian简称执行计划,使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句是否存在语句或者是表结构的性能瓶颈。
(2).如何使用
Explain + SQL语句
如:对student表使用explain关键字执行以下的查询操作
执行计划包含的信息如下:
A:数据库表的读取顺序
B:数据读取操作的操作类型
C:哪一些索引可以使用
D:哪一些索引被实际使用
E:数据库表之间的引用
F:每一张表有多找行被优化器查询
(3).explian之id介绍
id字段表示的是select查询的序列号。包含一组数字。表示查询中执行select字句或者是操作表的顺序(其实就是表的读取顺序)。一般情况下有三种情况:
①:id相同,表示MySQL执行SQL语句中表的操作顺序由上而下(顺序加载);如:
②:id不同,如果是子查询,id的序号会递增。id的值越大优先级越高,越先被执行。
③:id相同又不同,同时存在;id如果相同,那么可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先被执行。
(4).explian之select_type和table介绍
①select_type
select_type常见的值有6个:simple,primarry,subquery,derived,union,union result。那么这一个select_type主要是指出查询的类型,用于区别是普通查询,联合查询,子查询等的复杂查询。那么这6中查询类型锁代表的查询情况如下:
simple:表示的是简单的select查询,查询中不包含子查询或者是UNION.
primeary:查询中若包含任何复杂的子部分,最外层查询则被标记为primary.
subquery:在select或者是where列表中包含了子查询
derived:在from列表中包含的子查询被标记为derived(衍生),MySQL会递归执行这一些子查询,把结果放在临时表中。
union:若第二个select出现在UNION之后,则被标记为UNION;若UNION包含在from子句的子查询中,外层select将被标记为:derived
union result:从UNION表获取结果的SELECT
②:table
table就是操作执行的数据库库表。
(5).explian之type介绍
type字段显示的值是访问类型排序,是一个较为关键的是否优化的显示信息,显示的内容是查询使用了何种类型。其值反应从最好到最差依次是:
System > const > eq_ref > ref > range > index > All
那么,我们在实际的开发和优化的过程中至少要达到range级别,最好能够达到ref级别。下面,我们一起来看一下每一个值分别代表的是什么内容以及使用案例如下:
数据库包以及内容如下:
System:表只有一行记录(等价于系统表)。这是const类型的特例,平时不会出现,这一个可以忽略不计。
const:表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据。所以很快,如果说将主键 置于条件查询的where列表中,MySQL就能将该查询转化为一个常量。
eq_ref:唯一索引扫描,对于每一个索引键,表中只有一条记录与之匹配,常用于主键或者是唯一索引扫描。
ref:非唯一性索引扫描,返回匹配某一个单独值的所有行。本质上也是一种索引访问,它返回的所有匹配某一个值的行。然而它
可能找到多个符合条件的行,所以它应该属于查找和扫描的混合体。
range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪一个索引。一般就是在你的where语句中出现了 between、>、<、in等的查询。这一种范围扫描索引扫描比全表扫描要好。因为它只需要开始于索引的某一个点,而结束
另一个点,不用扫描全部索引。
index:index 又称为full index Scan,index与ALL的区别为index类型只遍历索引树,这一个通常比ALL快,因为索引文件通常比数
据文件小(也就是说ALL和index都是全读表,但是index是从索引中读取,ALL是从硬盘中读取)。
ALL:full table scan,将遍历全表找到匹配的行。
(5).explian之possible_key和key介绍
①possible_key:显示可能应用在这张表中的索引,一个或者是多个。查询涉及到的字段上若存在索引,则将会被列出。但是呢不一定在查询中实际被使用到。
②key:实际被使用的索引,如果值为null,表示么有使用索引。若查询中使用了覆盖索引,则该索引仅出现在key列表中。
索引覆盖:当我们进行查询的时候的字段和我们所创建的索引的内容和顺序一致的时候。这一种情况就叫索引覆盖。
索引覆盖:查询的时候就仅仅只需要在索引上去查找数据,而不需要全表扫描。所以type是index。
(6).explian之key_len介绍
key_len表示的是索引中使用的字节数,可以通过该列计算查询中使用的索引的长度。在不损失精度的情况下,长度越短越好。那么key_len显示的值是索引字段的最大可能长度,并不是实际使用长度。也就是说key_len是根据表的定义计算而得,不是通过表内检索出来的。
(6).explian之ref介绍
ref:显示索引的哪一列被使用了,如果可能,是一个常数。哪一些列或常量被用于查找索引列上的值。
(7).explian之rows介绍
rows:根据表的统计信息以及索引的选用情况,大致的估计算出找到所需的的记录所需要读取的行数。该值越小越好。
(8).explian之Extra介绍
Extra:包含不合适显示在其他列中但是十分重要的额外信息。
常见的几种值介绍:
①:Using filesort:说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索 引完成排序的操作称为"文件排序"。出现这样的情况表明操作的SQL有较为严重的问题。需要及时的处理。
②:Using temporary:使用了临时表保存中间的结果,MySQL在对查询结果排序的时候使用了临时表。常用于排序order by和分 组查询 group by。出现了这一种情况的时候就较为严重了,往往会较大程度的拖慢数据库性能。所以在使
用group by的时候需要尽量的按照我们创建好的索引的顺序来做。
③:Using index:表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!如果同时出 现Using where,表明索引被用来执行索引键值的查找;如果没有出现Using where,表明索引用来读取数据 而不是执行查找动作(可以直接在索引上读取数据)。
注意事项:
使用覆盖索引的时候,一定要注意select 列表中值能够读取所需的列,而不能够全部读取(即:select *)。
但是呢,我们为了方便不能够把所有的字段一起做索引,这样会导致索引的文件过大,而导致查询的性能下降。
④:Using where:使用了where条件过滤。
⑤:Using join buffer:在使用join关键字的时候使用连接缓存。如果join的操作较多,可以在配置文件中修改缓冲buff大小
⑥:impossible where:where字句的值总是false,不能够获取任何的内容。
⑦:select table optimized away:在没有group by的情况下,基于所有优化MIN/MAX操作或者对于MyISAM存储引擎优化count(*)操作,不必等到执行阶段在计算。查询执行计划生成的阶段即可完成优化。
⑧:distinct:优化destinct操作,在找到第一匹配的元组后立即停止找同样值的动作。