全面分析SQL优化 -- explain详解
索引常用操作
1. 查询索引
show index from tablename;
2. 增加索引
普通索引: alter table 表名 add index 索引名(需要添加为索引的列);
唯一索引: alter table 表名 add UNIQUE [indexName] ON (username(length));
组合索引: alter TABLE mytable add index index1_index2_index3 (index1,index2,index3);
主键索引: 一般建表的时候通过 PRIMARY KEY(indexName) 添加. 当然也可以通过 ALTER 命令;
3. 删除索引
alter table 表名 drop index index_name;
drop index index_name on 表名;
索引优化 – explain
优化之前,在查询语句前使⽤explain关键字,查看SQL语句的执⾏计划,判断该查询语句是否使用了索引。
EXPLAIN : 模拟Mysql优化器是如何执行SQL查询语句的,从而知道Mysql是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。
例如
mysql> explain select * from tb_user;
看到上面这个表格,你可能会有疑问各个列名代表什么意思?
先看看官网文档表格的中文版
下面通过一番操作来看看每个列是啥含义。
(1)id列
(1) id 相同执行顺序由上到下
表1:3 表2:4 表3:5
执行顺序:表1 表2 表4: 这里主要是减少计算过程的使用量;
注意:这里如果id相同,会尽量将数据小的表优先查询!!
(2) id 不相同,越大越优先;
子查询:最内层先执行:上一层执行;
(3)id相同与不同并存;
先优先级;然后按照从上往下依次执行;
(2)select_type列:数据读取操作的操作类型
其中:
1. SIMPLE:简单的select 查询,SQL中不包含子查询或者UNION。(不办含子查询和union)
2. PRIMARY:查询中包含复杂的子查询部分,最外层查询被标记为PRIMARY(最外层);
3. SUBQUERY:在select 或者WHERE 列表中包含了子查询;(非最外层)
4. DERIVED:在FROM列表中包含的子查询会被标记为DERIVED(衍生表),MYSQL会递归执行这些子查询,把结果集放到零时表中。
(a).在from 子查询中,只有一张表,临时表:例如:
select cr.name from (select * from course where tid in(1,2)) cr;
(b). 如果from中,table1 union table2 ;其中,table1 就是DERIVED table2就是 union;
select cr.cname from (select * from course where tid=1 union select * from course where tid=2 ) cr;
5、UNION:如果第二个SELECT 出现在UNION之后,则被标记位UNION;如果UNION包含在FROM子句的子查询中,则外层SELECT 将被标记为DERIVED;
select cr.cname from (select * from course where tid=1 union select * from course where tid=2 ) cr;
6、UNION RESULT:从UNION表获取结果的select;
(3)table列:该行数据是关于哪张表
(4)type列
访问类型(查询类型,索引类型 ) 由好到差system > const > eq_ref > ref > range > index > ALL。 其中,system const 是理想情况,实际可以达到的: ref > range ;
注意: 要对type优化的前提:有索引;
各个类型含义:
1. system:表只有一条记录(等于系统表),这是const类型的特例,平时业务中不会出现。
2. const:通过索引一次查到数据,该类型主要用于比较primary key 或者unique 索引,因为只匹配一行数据,所以很快;如果将主键置于WHERE语句后面,Mysql就能将该查询转换为一个常量。
3.eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配(唯一行数据)。常见于主键或者唯一索引扫描。
select t.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid;
t.tcid = tc.tcid; 分别是主键索引和唯一索引;
eq_ref:要求主查询出来的数据只有一条!! 并且不能为0;
以上sql; 用到的索引是 t.tcid = tc.tcid;这里 t.tcid的条数与 tc.tcid的条数必须相同才可以达到要求;
4. ref(普通索引):非唯一索引扫描,返回匹配某个单独值得所有行,本质上是一种索引访问,它返回所有匹配某个单独值的行,就是说它可能会找到多条符合条件的数据,所以他是查找与扫描的混合体。
详解:这种类型表示mysql会根据特定的算法快速查找到某个符合条件的索引,而不是会对索引中每一个数据都进行一 一的扫描判断,也就是所谓你平常理解的使用索引查询会更快的取出数据。而要想实现这种查找,索引却是有要求的,要实现这种能快速查找的算法,索引就要满足特定的数据结构。简单说,也就是索引字段的数据必须是有序的,才能实现这种类型的查找,才能利用到索引。
根据索引查询,返回数据不唯一; 0或者多;
5. range:只检索给定范围的行,使用一个索引来选着行。key列显示使用了哪个索引。一般在你的WHERE 语句中出现between 、< 、> 、in 等查询,这种给定范围扫描比全表扫描要好。因为他只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。
根据索引,范围查询;
6. index:FUll Index Scan 扫描遍历索引树(index:这种类型表示是mysql会对整个该索引进行扫描。要想用到这种类型的索引,对这个索引并无特别要求,只要是索引,或者某个复合索引的一部分,mysql都可能会采用index类型的方式扫描。但是呢,缺点是效率不高,mysql会从索引中的第一个数据一个个的查找到最后一个数据,直到找到符合判断条件的某个索引)。
index:查询所有索引列查询一遍;
7. ALL 全表扫描 从磁盘中获取数据 百万级别的数据ALL类型的数据尽量优化。
把整个表查询了一遍;
(5)ken_len列
表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好。key_len 显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出来的。
(6)ref列
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值。
(7)rows列(每张表有多少行被优化器查询)
根据表统计信息及索引选用的情况,大致估算找到所需记录需要读取的行数。
(8)Extra列
扩展属性,但是很重要的信息。
1. using temporary; 性能损耗大 尽量避免采用临时表 ,一般出现在group by 语句中;
避免using temporary;
from ---- where ----- group by ----- having ---- select ---- order by ---- limit —;
这里在group by 中;查询哪些列,就group by 那些列;
select a1 from test02 where a1 in (1,2,4) group by a1;—一张表
select a1 from test02 where a1 in(1,2,3) group by a2;—不是一张表;–using temporary;
2. using index;性能提升;索引覆盖;
原因:不需要读取源文件,只要从索引文件中就可以查询;(不需要回表查询)
比如:索引是age ;
select age from ... where age ="";
查询的是索引列,并且where、group 中是通过索引列过滤的
a.如果用到了索引覆盖,有where,出现在possible key ; key;
b. 如果没有where ,索引出现在key;不出现在;
3. using where ;(需要回原表查询);
select age,name from pp where age=""; 这个语句需要回原表查询;
上一篇: 美化MyEclipse
下一篇: 使用MyEclipse导入项目方法