sql执行计划怎么看,dbvisualizer看sql执行计划

目录一、执行计划分析二、SQL执行计划中的参数讲解——explain中的id1、id值相同,从上往下顺序执行。2、ID值不同,id值越大越优先查询3、id值有相同,又有不同。id值越大越优先;id值相

目录一、执行计划分析二、SQL执行计划中的参数讲解——explain中的id1、id值相同,从上往下顺序执行。2、ID值不同,id值越大越优先查询3、id值有相同,又有不同。id值越大越优先;id值相同,从上往下顺序执行二、SQL执行计划中的参数讲解——explain中的select_type三、SQL执行计划中的参数讲解——explain中的table四、SQL执行计划中的参数讲解——explain中的type1、type字段中的——system2、type字段中的——const3、type字段中的——eq_ref4、type字段中的——ref5、type字段中的——range6、type字段中的——index7、type字段中的——all四、SQL执行计划中的参数讲解——explain中的possible_keys五、SQL执行计划中的参数讲解——explain中的key六、SQL执行计划中的参数讲解——explain中的key_len七、SQL执行计划中的参数讲解——explain中的ref八、SQL执行计划中的参数讲解——explain中的rows九、SQL执行计划中的参数讲解——explain中的Extra1、Extra字段中——using filesort2、Extra字段中——using temporary3、Extra字段中——using index4、Extra字段中——using where十、优化案例,单表优化、两表优化、三表优化十一、避免索引失效的一些原则

前不久看了SQL优化的视频,学的时候醍醐灌顶,学完后发现就是在围绕着explain的各个字段讲解,先把学习的知识梳理一下,当然自己还是有很多不会的地方,后期不断完善。

SQL执行顺序先执行SQL语句中的from,在执行on.. join ..where ..group by ....having ...,最后执行select dinstinct ..order by limit ...

from .. on.. join ..where ..group by ....having ...select dinstinct ..order by limit ...

一、执行计划分析

通过explain可以知道mysql是如何处理语句的,并分析出查询或是表结构的性能瓶颈,其实就是在干查询优化器的事,通过expalin可以得到查询执行计划。

#语法:explain +SQL语句explainselect* from tb

各字段含义

id : 编号select_type :查询类型table :表type :类型possible_keys :预测用到的索引key :实际使用的索引key_len :实际使用索引的长度ref :表之间的引用rows :通过索引查询到的数据量Extra :额外的信息

下面讲解explain中各字段的具体含义,我们只关注三种,分别是type,key,rows

二、SQL执行计划中的参数讲解——explain中的id

explain中id是SQL执行顺序的标识,id的返回结果是数字,id 值越大优先级越高,越先被执行;id 相同,从上往下顺序执行。返回结果有三种情况。

目录1、id值相同,从上往下顺序执行。2、ID值不同,id值越大越优先查询3、id值有相同,又有不同。id值越大越优先;id值相同,dbvisualizer看sql执行计划,从上往下顺序执行,

1、id值相同,从上往下顺序执行。

案例如下

explain select t.* from teacher t,course c,teacherCard tc wheret.tid=c.tid and t.tcid = tc.tcid and (c.cid=2 or tc.tcid=3)

图1

在上图SQL逻辑中,id值相同都为1,从上往下顺序执行。先执行teacher表(t表),在执行teacherCard 表(tc表),最后执行course 表(c表)。

建表:create table course(cid int(3),cname varchar(20),tid int(3));create table teacher(tid int(3),tname varchar(20),tcid int(3));create table teacherCard(tcid int(3),tcdesc varchar(200));插入数据insert into course values(1,&39;,1);insert into course values(2,&39;,1);insert into course values(3,&39;,2);insert into course values(4,&39;,3);insert into teacher values(1,&39;,1);insert into teacher values(2,&39;,2);insert into teacher values(3,&39;,3);insert into teacherCard values(1,&39;) ;insert into teacherCard values(2,&39;) ;insert into teacherCard values(3,&39;) ;

改变表中数据量会影响表的执行顺序

图1表中数据量:teacher表3条teacherCard 表3条course 表4条

改变teacher表数据条数,增加3条数据

insert into teacher values(4,&39;,4);insert into teacher values(5,&39;,5);insert into teacher values(6,&39;,6);

查看表的执行顺序

Mysql中查看执行计划的方式有两种 : 1. 使用desc    2.使用 explain  使用它俩的效果是一样的 接下来要通过执行计划知道sql是怎么执行的 执行计划中有几个重要的字段, 分别是 id,  tab。

图2

我们可以看见修改了表数据量之后,表的执行也改变了。先执行teacherCard 表(tc表),在执行course 表(c表),最后执行teacher表(t表)。

表的执行顺序因数量的个数改变而改变的原因笛卡儿积。数据量小对程序占用内存小,优先计算(数据小的表,优先查询)

2、ID值不同,id值越大越优先查询

案例如下

mysql> explain select tc.tcdesc from teacherCard tc where tc.tcid = -> (select t.tcid from teacher t wheret.tid =-> (select c.tid from course c where c.cname = &39;)-> );+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+|1 | PRIMARY | tc| ALL| NULL| NULL| NULL| NULL|3 | Using where ||2 | SUBQUERY| t | ALL| NULL| NULL| NULL| NULL|6 | Using where ||3 | SUBQUERY| c | ref| cname_index | cname_index | 23| const |1 | Using index condition |+----+-------------+-------+------+---------------+-------------+---------+-------+------+-----------------------+

在上面逻辑中,id值不相同,id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)从id字段和table字段可以知道程序在底层先执行course 表(c表),在执行teacher表(t表),最后执行teacherCard 表(tc表)

3、id值有相同,又有不同。id值越大越优先;id值相同,从上往下顺序执行

案例如下

方法/步骤 首先先建一个查询的窗口中,选中数据库,点击新建查询。弹出了一个新建查询的窗口的界面中,输入需要执行的sql的语句。sql输入完成之后,选中需要的执行的sql的语句。然后进行点击菜单中的查询的按钮选项。可以弹出。

mysql> explain select t.tname ,tc.tcdesc from teacher t,teacherCard tc where t.tcid= tc.tcid-> and t.tid = (select c.tid from course c where cname = &39;) ;+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra|+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+|1 | PRIMARY | tc| ALL| NULL| NULL| NULL| NULL|3 | NULL ||1 | PRIMARY | t | ALL| NULL| NULL| NULL| NULL|6 | Using where; Using join buffer (Block Nested Loop) ||2 | SUBQUERY| c | ref| cname_index | cname_index | 23| const |1 | Using index condition|+----+-------------+-------+------+---------------+-------------+---------+-------+------+----------------------------------------------------+

在上面案例中,id值有相同,又有不同。先执行course 表(c表),在执行teacherCard 表(tc表),最后执行teacher表(t表)。

二、SQL执行计划中的参数讲解——explain中的select_type

select_type是查询类型,常见的查询类型如下。

1、 简单查询,查询SQL中不包含子查询或者UNION2、PRIMARY: 查询中若包含复杂的子查询,最外层的查询则标记为3、SUBQUERY : 包含子查询SQL中的 子查询 (非最外层)4、DERIVED : 衍生查询(使用到了临时表)。在from列表中包含子查询被标记为DRIVED衍生,MYSQL会递归执行这些子查询,把结果放到临时表中5、UNION: 若第二个SELECT出现在union之后,则被标记为UNION,若union包含在from子句的子查询中,外层select被标记为:derived6、UNION RESULT: 从union表获取结果的select

三、SQL执行计划中的参数讲解——explain中的table

显示这一行的数据是关于哪张表的,有时不是真实的表名字,看到的是derivedx(x是个数字,我的理解是第几步执行的结果)

mysql> explain select cr.cname from->( select * from course where tid = 1 union select * from course where tid = 2 ) cr;+----+--------------+------------+------+---------------+------+---------+------+------+-----------------+| id | select_type| table| type | possible_keys | key| key_len | ref| rows | Extra |+----+--------------+------------+------+---------------+------+---------+------+------+-----------------+|1 | PRIMARY| <derived2> | ALL| NULL| NULL | NULL| NULL |8 | NULL||2 | DERIVED| course | ALL| NULL| NULL | NULL| NULL |4 | Using where ||3 | UNION| course | ALL| NULL| NULL | NULL| NULL |4 | Using where || NULL | UNION RESULT | <union2,3> | ALL| NULL| NULL | NULL| NULL | NULL | Using temporary |+----+--------------+------------+------+---------------+------+---------+------+------+-----------------+

四、SQL执行计划中的参数讲解——explain中的type

表示MySQL在表中找到所需行的方式,又称“访问类型”,sql查询优化中一个很重要的指标,结果值从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL一般来说,好的sql查询至少达到range级别,最好能达到ref

目录:1、type字段中的——system2、type字段中的——const3、type字段中的——eq_ref4、type字段中的——ref5、type字段中的——range6、type字段中的——index7、type字段中的——all

1、type字段中的——system

实现场景:当表里面只有一行数据的时候就会这样,而且不管有没有索引都一样,这是const连接类型的特殊情况。实现只有一条数据的系统表 ;或衍生表只有一条数据的主查询

2、type字段中的——const

实现场景:当查询只有唯一的一条记录被匹配,并且使用作为查询条件时, MySQL 会视查询出来的值为常数(可以为字符串或者数字),这种类型非常快。和system不同的地方是system是表里面只有一行数据,而const有多行数据,const是只有一行数据被匹配。

案例如下

create table test01(tid int(3), tname varchar(20));插入数据insert into test01 values(1,&39;) ;insert into test01 values(2,&39;) ;增加索引alter table test01 add constraint tid_pk primary key(tid) ;

查询表中所有字段mysql> explain select * from test01 where tid =1 ;+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------+| id | select_type | table| type| possible_keys | key | key_len | ref | rows | Extra |+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------+|1 | SIMPLE| test01 | const | PRIMARY | PRIMARY | 4 | const |1 | NULL|+----+-------------+--------+-------+---------------+---------+---------+-------+------+-------+

3、type字段中的——eq_ref

唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多 、不能0),常见于唯一索引 和主键索引。必须满足查询结果和表中数据是一致的。案例如下

create table teacher(tid int(3),tname varchar(20),tcid int(3));create table teacherCard(tcid int(3),tcdesc varchar(200));insert into teacher values(1,&39;,1);insert into teacher values(2,&39;,2);insert into teacher values(3,&39;,3);insert into teacher values(4,&39;,4);insert into teacher values(5,&39;,5);insert into teacher values(6,&39;,6);insert into teacherCard values(1,&39;) ;insert into teacherCard values(2,&39;) ;insert into teacherCard values(3,&39;) ;建索引alter table teacherCard add constraint pk_tcid primary key(tcid);alter table teacher add constraint uk_tcid unique index(tcid) ;

2、teacher表和teacherCard 都有唯一索引tcid,查询teacherCard 表的tcid,type类型是ref mysql> explain select tc.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid ;+----+-------------+-------+-------+---------------+---------+---------+--------------+------+-------------+| id | select_type | table | type| possible_keys | key | key_len | ref| rows | Extra |+----+-------------+-------+-------+---------------+---------+---------+--------------+------+-------------+|1 | SIMPLE| tc| index | PRIMARY | PRIMARY | 4 | NULL |3 | Using index ||1 | SIMPLE| t | ref | uk_tcid | uk_tcid | 5 | test.tc.tcid |1 | Using index |+----+-------------+-------+-------+---------------+---------+---------+--------------+------+-------------+

为什么上面type类型不是eq_ref原因:teacher有6条数据,索引查到的数据只有3条,还有3条数据没查到,没查到的数据结果就是0。

上面查询如何达到eq_ref

#删除teacher表中的三条数据delete from teacher where tid>3;

删除数据后查看type类型

1、直接File->New->Explain Plan Window,在窗口中执行sql可以查看计划结果。其中,Cost表示cpu的消耗,单位为n%,Cardinality表示执行的行数,等价Rows。2、先执行 EXPLAIN PLAN FOR select * from tableA where paraA=。

mysql> explain select t.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid ;+----+-------------+-------+--------+---------------+---------+---------+-------------+------+--------------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra|+----+-------------+-------+--------+---------------+---------+---------+-------------+------+--------------------------+|1 | SIMPLE| t | index| uk_tcid | uk_tcid | 5 | NULL|3 | Using where; Using index ||1 | SIMPLE| tc| eq_ref | PRIMARY | PRIMARY | 4 | test.t.tcid |1 | Using index|+----+-------------+-------+--------+---------------+---------+---------+-------------+------+--------------------------+

以上SQL,用到的索引是 t.tcid,即teacher表中的tcid字段;如果teacher表的数据个数 和 连接查询teacherCard 表的数据个数一致(都是3条数据),则有可能满足eq_ref级别;否则无法满足。

4、type字段中的——ref

非唯一性索引,对于每个索引键的查询,返回匹配的所有行(0行,多行或者一行)

出现该连接类型的条件是: 查找条件列使用了索引而且不为主键和unique。其实,意思就是虽然使用了索引,但该索引列的值并不唯一,有重复。这样即使使用索引快速查找到了第一条数据,仍然不能停止,要进行目标值附近的小范围扫描。但它的好处是它并不需要扫全表,因为索引是有序的,即便有重复值,也是在一个非常小的范围内扫描。

准备数据: insert into teacher values(4,&39;,4) ; insert into teacherCard values(4,&39;);添加索引:alter table teacher add index index_name (tname) ;

mysql> explain select * from teacher where tname=&39;;+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key| key_len | ref | rows | Extra |+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+|1 | SIMPLE| teacher | ref| index_name| index_name | 23| const |2 | Using index condition |+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+mysql> explain select * from teacher where tname=&39;;+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key| key_len | ref | rows | Extra |+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+|1 | SIMPLE| teacher | ref| index_name| index_name | 23| const |1 | Using index condition |+----+-------------+---------+------+---------------+------------+---------+-------+------+-----------------------+

5、type字段中的——range

range指的是有范围的索引扫描,where后面是一个范围查询(between ,> < >=,**特殊:in有时候会失效 **,从而转为 无索引all)

1、in范围查询时索引失效mysql> explain select t.* from teacher t where t.tid in (1,2) ;+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1 | SIMPLE| t | ALL| tid_index | NULL | NULL| NULL |4 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+#2、<范围查询时type 类型是rangemysql> explain select t.* from teacher t where t.tid <3 ;+----+-------------+-------+-------+---------------+-----------+---------+------+------+-----------------------+| id | select_type | table | type| possible_keys | key | key_len | ref| rows | Extra |+----+-------------+-------+-------+---------------+-----------+---------+------+------+-----------------------+|1 | SIMPLE| t | range | tid_index | tid_index | 5 | NULL |1 | Using index condition |+----+-------------+-------+-------+---------------+-----------+---------+------+------+-----------------------+

6、type字段中的——index

查询全部索引中数据

mysql> explain select tid from teacher;--tid 是索引, 只需要扫描索引表,不需要所有表中的所有数据+----+-------------+---------+-------+---------------+-----------+---------+------+------+-------------+| id | select_type | table | type| possible_keys | key | key_len | ref| rows | Extra |+----+-------------+---------+-------+---------------+-----------+---------+------+------+-------------+|1 | SIMPLE| teacher | index | NULL| tid_index | 5 | NULL |4 | Using index |+----+-------------+---------+-------+---------------+-----------+---------+------+------+-------------+

7、type字段中的——all

查询全部表中的数据。这便是所谓的“全表扫描”,如果是展示一个数据表中的全部数据项,倒是觉得也没什么,如果是在一个查找数据项的sql中出现了all类型,那通常意味着你的sql语句处于一种最原生的状态,有很大的优化空间。

mysql> explain select cid from course;--cid不是索引,需要全表所有,即需要所有表中的所有数据+----+-------------+--------+------+---------------+------+---------+------+------+-------+| id | select_type | table| type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+--------+------+---------------+------+---------+------+------+-------+|1 | SIMPLE| course | ALL| NULL| NULL | NULL| NULL |4 | NULL|+----+-------------+--------+------+---------------+------+---------+------+------+-------+

四、SQL执行计划中的参数讲解——explain中的possible_keys

possible_keys可能用到的索引,是一种预测。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用,如果为空,说明没有可用的索引。

mysql> explain select cid from course;+----+-------------+--------+------+---------------+------+---------+------+------+-------+| id | select_type | table| type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+--------+------+---------------+------+---------+------+------+-------+|1 | SIMPLE| course | ALL| NULL| NULL | NULL| NULL |4 | NULL|+----+-------------+--------+------+---------------+------+---------+------+------+-------+

该查询中possible_keys 为null,说明没有索引。

五、SQL执行计划中的参数讲解——explain中的key

实际使用到的索引

六、SQL执行计划中的参数讲解——explain中的key_len

key_len 索引的长度 ,用于判断复合索引是否被完全使用

案例如下

#创建一张表create table test_kl(name char(20));创建索引alter table test_kl add index index_name(name) ;

查看执行计划

mysql> explain select * from test_k2 where name =&39; ; +----+-------------+---------+------+---------------+------------+---------+-------+------+--------------------------+| id | select_type | table | type | possible_keys | key| key_len | ref | rows | Extra|+----+-------------+---------+------+---------------+------------+---------+-------+------+--------------------------+|1 | SIMPLE| test_k2 | ref| index_name| index_name | 23| const |1 | Using where; Using index |+----+-------------+---------+------+---------------+------------+---------+-------+------+--------------------------+

在utf8:1个字符站3个字节如果索引字段可以为Null,则会使用1个字节用于标识。20*1=20 + 1(null) +2(用2个字节 标识可变长度,字段类型是可变长度) =23

utf8:1个字符3个字节gbk:1个字符2个字节latin:1个字符1个字节

复合索引案例如下

alter table test_k2 add column name1 varchar(20) ;--name1可以为nulldrop index index_name on test_k2 ;增加一个复合索引 alter table test_k2 add index name_name1_index (name,name1) ;

七、SQL执行计划中的参数讲解——explain中的ref

注意与type中的ref值区分,显示索引的哪一列被使用了 。返回两种结果,const(是常量则该字段结果是const),或者使用了那个字段。

alter table courseadd index tid_index (tid) ;

mysql> explain select * from course c,teacher t where c.tid = t.tidand t.tname =&39; ;+----+-------------+-------+------+----------------------+------------+---------+------------+------+------------------------------------+| id | select_type | table | type | possible_keys| key| key_len | ref| rows | Extra|+----+-------------+-------+------+----------------------+------------+---------+------------+------+------------------------------------+|1 | SIMPLE| t | ref| index_name,tid_index | index_name | 23| const|1 | Using index condition; Using where ||1 | SIMPLE| c | ref| tid_index| tid_index| 5 | test.t.tid |1 | NULL |+----+-------------+-------+------+----------------------+------------+---------+------------+------+------------------------------------+

八、SQL执行计划中的参数讲解——explain中的rows

被索引优化查询的数据个数 (实际通过索引而查询到的 数据个数)explain select * from course c,teacher t where c.tid = t.tidand t.tname = &39; ;

九、SQL执行计划中的参数讲解——explain中的Extra

Extra其他信息,出现Using filesort、Using temporary 意味着不能使用索引,效率会受到重大影响。应尽可能对此进行优化

1、Extra字段中——using filesort

性能消耗大;需要“额外”的一次排序(或者是额外得一次查询),常见于 order by 语句中。排序:排序得前提是先查询,在排序。比如需要对10个人根据年龄排序,所以排序之前需要先排序

案例如下

create table test02(a1 char(3), a2 char(3), a3 char(3), index idx_a1(a1), index idx_a2(a2), index idx_a3(a3));

mysql> explain select * from test02 where a1 =&39; order by a2 ; +----+-------------+--------+------+---------------+--------+---------+-------+------+----------------------------------------------------+| id | select_type | table| type | possible_keys | key| key_len | ref | rows | Extra|+----+-------------+--------+------+---------------+--------+---------+-------+------+----------------------------------------------------+|1 | SIMPLE| test02 | ref| idx_a1| idx_a1 | 4 | const |1 | Using index condition; Using where; Using filesort |+----+-------------+--------+------+---------------+--------+---------+-------+------+----------------------------------------------------+

Extra字段中出现了Using filesort。

小结:对于单索引, 如果排序和查找是同一个字段,则不会出现using filesort;如果排序和查找不是同一个字段,则会出现using filesort;如何避免: where哪些字段,就order by那些字段2

复合索引——分析Extra字段复合索引,不能跨列(最佳左前缀)

drop index idx_a1 on test02;drop index idx_a2 on test02;drop index idx_a3 on test02;alter table test02 add index idx_a1_a2_a3 (a1,a2,a3) ;

test02 有复合索引idx_a1_a2_a3 (a1,a2,a3) ,where条件是a1,排序是a3。跨列了,所以出现了Using filesort。

mysql> explain select *from test02 where a1=&39; order by a3 ;+----+-------------+--------+------+---------------+--------------+---------+-------+------+------------------------------------------+| id | select_type | table| type | possible_keys | key| key_len | ref | rows | Extra|+----+-------------+--------+------+---------------+--------------+---------+-------+------+------------------------------------------+|1 | SIMPLE| test02 | ref| idx_a1_a2_a3| idx_a1_a2_a3 | 4 | const |1 | Using where; Using index; Using filesort |+----+-------------+--------+------+---------------+--------------+---------+-------+------+------------------------------------------+

Extra字段存在Using filesort

mysql> explain select *from test02 where a2=&39; order by a3 ;+----+-------------+--------+-------+---------------+--------------+---------+------+------+------------------------------------------+| id | select_type | table| type| possible_keys | key| key_len | ref| rows | Extra|+----+-------------+--------+-------+---------------+--------------+---------+------+------+------------------------------------------+|1 | SIMPLE| test02 | index | NULL| idx_a1_a2_a3 | 12| NULL |1 | Using where; Using index; Using filesort |+----+-------------+--------+-------+---------------+--------------+---------+------+------+------------------------------------------+

Extra字段无Using filesort

mysql> explain select *from test02 where a1=&39; order by a2 ;+----+-------------+--------+------+---------------+--------------+---------+-------+------+--------------------------+| id | select_type | table| type | possible_keys | key| key_len | ref | rows | Extra|+----+-------------+--------+------+---------------+--------------+---------+-------+------+--------------------------+|1 | SIMPLE| test02 | ref| idx_a1_a2_a3| idx_a1_a2_a3 | 4 | const |1 | Using where; Using index |+----+-------------+--------+------+---------------+--------------+---------+-------+------+--------------------------+

小结:避免where和order by 按照复合索引的顺序使用,不要跨列或无序使用。

2、Extra字段中——using temporary

mysql> explain select a1 from test02 where a1 in (&39;,&39;,&39;) group by a2;+----+-------------+--------+-------+---------------+--------------+---------+------+------+-----------------------------------------------------------+| id | select_type | table| type| possible_keys | key| key_len | ref| rows | Extra |+----+-------------+--------+-------+---------------+--------------+---------+------+------+-----------------------------------------------------------+|1 | SIMPLE| test02 | index | idx_a1_a2_a3| idx_a1_a2_a3 | 12| NULL |1 | Using where; Using index; Using temporary; Using filesort |+----+-------------+--------+-------+---------------+--------------+---------+------+------+-----------------------------------------------------------+

出现了Using temporary,根据a2分组,但是没查询a2.

3、Extra字段中——using index

出现using index性能会提升,即索引覆盖(覆盖索引)。索引覆盖该SQL不读取原文件,只从索引文件中获取数据 (不需要回表查询),只要使用到的列 全部都在索引中,就是索引覆盖using index。

案例如下

39;&39;' ;+----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+| id | select_type | table| type| possible_keys | key| key_len | ref| rows | Extra|+----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+|1 | SIMPLE| test02 | index | idx_a1_a2_a3| idx_a1_a2_a3 | 12| NULL |1 | Using where; Using index |+----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+

4、Extra字段中——using where

using where 回表查询,需要在索引中查,有需要在原表中查就会出现using where

mysql> explain select a1,a3 from test02 where a3 = &39; ; +----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+| id | select_type | table| type| possible_keys | key| key_len | ref| rows | Extra|+----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+|1 | SIMPLE| test02 | index | NULL| idx_a1_a2_a3 | 12| NULL |1 | Using where; Using index |+----+-------------+--------+-------+---------------+--------------+---------+------+------+--------------------------+

5、Extra字段中——impossible where

where子句永远为false,会出现impossible where

案例如下:

mysql> explain select * from test02 where a1=&39; and a1=&39;;+----+-------------+-------+------+---------------+------+---------+------+------+------------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra|+----+-------------+-------+------+---------------+------+---------+------+------+------------------+|1 | SIMPLE| NULL| NULL | NULL| NULL | NULL| NULL | NULL | Impossible WHERE |+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

a1不会出现即等于x,又等于y

十、优化案例,单表优化、两表优化、三表优化

1、单表优化

小结:a.最佳做前缀,保持索引的定义和使用的顺序一致性b.索引需要逐步优化c.将含In的范围查询 放到where条件的最后,防止失效。

2、两表优化

1、索引往哪张表加?小表驱动大表2、索引建立经常使用的字段上一般情况对于左外连接,给左表加索引;右外连接,给右表加索引3、join时,为什么需要用小表驱动大表?原因是join时是双层循环,一般建议将数据小的循环放外层;数据大的循环放内存。在编程语言中,外层越小,内存越大,性能越高(小表在左,外层循环少,依赖的原则是程序优化)

3、三张表优化A B C

a.小表驱动大表b.索引建立在经常查询的字段上--where 字段加索引,和常用字段加索引

十一、避免索引失效的一些原则

使用数据如下

create table book(bid int(4) primary key, name varchar(20) not null, authorid int(4) not null, publicid int(4) not null, typeid int(4) not null );insert into book values(1,&39;,1,1,2) ;insert into book values(2,&39;,2,1,2) ;insert into book values(3,&39;,3,2,1) ;insert into book values(4,&39;,4,2,3) ; alter table book add index idx_bta (bid,typeid,authorid);

1、复合索引a.复合索引,不要跨列或无序使用(最佳左前缀)(a,b,c)b.复合索引,尽量使用全索引匹配(a,b,c)2、不要在索引上进行任何操作(计算、函数、类型转换),否则索引失效

mysql> explain select * from book where authorid = 1 and typeid = 2 ;---用到了at 2个索引+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------+|1 | SIMPLE| book| ref| idx_atb | idx_atb | 8 | const,const |1 | NULL|+----+-------------+-------+------+---------------+---------+---------+-------------+------+-------+1 row in set (0.00 sec)mysql> explain select * from book where authorid = 1 and typeid*2 = 2 ; --用到了a1个索引+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+|1 | SIMPLE| book| ref| idx_atb | idx_atb | 4 | const |1 | Using index condition |+----+-------------+-------+------+---------------+---------+---------+-------+------+-----------------------+1 row in set (0.00 sec)mysql> explain select * from book where authorid*2 = 1 and typeid*2 = 2 ; ----用到了0个索引+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1 | SIMPLE| book| ALL| NULL| NULL | NULL| NULL |4 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)mysql> explain select * from book where authorid*2 = 1 and typeid = 2 ;---用到了0个索引,--原因:对于复合索引,如果左边失效,右侧全部失效。(a,b,c),例如如果 b失效,则b c同时失效。+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1 | SIMPLE| book| ALL| NULL| NULL | NULL| NULL |4 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)

3、复合索引不能使用不等于(!= <>)或is null (is not null)复合索引不能使用不等于(!= <>)或is null (is not null),否则自身以及右侧所有全部失效。复合索引中如果有>,则自身和右侧索引全部失效。

案例如下

mysql> explain select * from book where authorid != 1 and typeid =2 ;+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1 | SIMPLE| book| ALL| idx_atb | NULL | NULL| NULL |4 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+1 row in set (0.00 sec)mysql> explain select * from book where authorid != 1 and typeid !=2 ;+----+-------------+-------+------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key| key_len | ref| rows | Extra |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+|1 | SIMPLE| book| ALL| idx_atb | NULL | NULL| NULL |4 | Using where |+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

SQL优化,是一种概率层面的优化。至于是否实际使用了我们的优化,需要通过explain进行推测。

体验概率情况(< > =)原因是服务层中有SQL优化器,可能会影响我们的优化。

drop index idx_typeid on book;drop index idx_authroid on book;alter table book add index idx_book_at (authorid,typeid);explain select * from book where authorid = 1 and typeid =2 ;--复合索引at全部使用explain select * from book where authorid > 1 and typeid =2 ; --复合索引中如果有>,则自身和右侧索引全部失效。explain select * from book where authorid = 1 and typeid >2 ;--复合索引at全部使用

明显的概率问题

explain select * from book where authorid < 1 and typeid =2 ;--复合索引at只用到了1个索引explain select * from book where authorid < 4 and typeid =2 ;--复合索引全部失效

我们学习索引优化 ,是一个大部分情况适用的结论,但由于SQL优化器等原因 该结论不是100%正确。一般而言, 范围查询(> < in),之后的索引失效。

sql执行计划怎么看

4、 like尽量以“常量”开头,不要以&39;开头,否则索引失效如下

select * from xx where name like &39; ; --name索引失效explain select * from teacherwhere tname like &39;; --tname索引失效explain select * from teacherwhere tname like &39;;explain select tname from teacherwhere tname like &39;;

如果必须使用like &39;进行模糊查询,可以使用索引覆盖挽救一部分。

5、尽量不要使用类型转换(显示、隐式),否则索引失效

explain select * from teacher where tname = &39; ;explain select * from teacher where tname = 123 ;//程序底层将 123 -> &39;,即进行了类型转换,因此索引失效

6、尽量不要使用or,否则索引失效

你好,有以下两个方法进行查看。方法1:根据sql_id查询sql的执行计划setlines2000setpages2000select*fromtable(dbms_xplan.display_cursor(‘fp3p7b9kk02xg’,‘0’));方法2:根据sql语句查询执行计划setautotracetracesetlines。

7、一些其他的优化方法

(1)exist和in

select ..from table where exist (子查询) ;select ..from table where 字段 in(子查询) ;

如果主查询的数据集大,则使用In ,效率高。如果子查询的数据集大,则使用exist,效率高。

(2)order by 优化using filesort 有两种算法:双路排序、单路排序 (根据IO的次数)MySQL4.1之前 默认使用 双路排序;双路:扫描2次磁盘(1:从磁盘读取排序字段 ,对排序字段进行排序(在buffer中进行的排序) 2:扫描其他字段 )--IO较消耗性能

MySQL4.1之后 默认使用 单路排序 : 只读取一次(全部字段),在buffer中进行排序。但种单路排序 会有一定的隐患 (不一定真的是“单路|1次IO”,有可能多次IO)。原因:如果数据量特别大,则无法 将所有字段的数据 一次性读取完毕,因此 会进行“分片读取、多次读取”。注意:单路排序 比双路排序 会占用更多的buffer。单路排序在使用时,如果数据大,可以考虑调大buffer的容量大小: set max_length_for_sort_data = 1024 单位byte

如果max_length_for_sort_data值太低,则mysql会自动从 单路->双路 (太低:需要排序的列的总大小超过max_length_for_sort_data定义的字节数)

提高order by查询的策略a.选择使用单路、双路 ;调整buffer的容量大小;b.避免select * ...c.复合索引 不要跨列使用 ,避免using filesortd.保证全部的排序字段 排序的一致性(都是升序 或 降序)

后记

最后SQL优化简单记录了,SQL优化也暂时学习到这,后期学习中会继续完善。文章写得不好,但是总比自己不梳理好。

如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论。

咱们下期见!答案获取方式:已赞 已评 已关~

学习更多JAVA知识与技巧,关注与私信博主(666)

上一篇 2023年02月17 14:31
下一篇 2023年02月11 10:22

相关推荐

  • 苹果怎么自定义铃声

    由于iOS系统相对封闭的特性,iPhone设置自定义铃声没法像安卓手机那样,随便一首歌都能直接设置为铃声。苹果手机设置自定义铃声主要有2个比较费劲的地方,一个是时长不超过40秒,且必须是.m4r格式铃

    2023年02月15 222
  • 怎么查询本机ip,本机当前IP地址

    不同的操作系统使用不同的方法查看计算机的本地IP:1、对于Windows,在命令提示行中输入命令“ipconfig”。可以通过按[Windows]+[R]键在弹出的框中输入“cmd”来打开命令提示行。

    2023年02月05 220
  • 太阳距离地球多少光年,天文望远镜看太阳吓人

    秦始皇在公元前221年统一了六国,然后建立起了秦朝,距今已经有2243年了。从物理学角度来讲,由于光的传播速度是有限的(每秒30万公里),在距离地球2243光年外的某个星球上,能否看到秦始皇统一六国登

    2023年03月17 230
  • 苹果怎么手写

    相信很多人平时开会,都在手写会议笔记,真的耗时又耗力,其实iPhone打开这个功能,10秒就能搞定2小时的会议纪要,开会再也不用手写了。①启用听写②添加语言③语音输入④生成笔记⑤会议神器⑥会议纪要iP

    2023年02月10 232
  • word怎么打平方,word公式编辑器里怎么打平方

    当我们在编辑WPS和word里的数字时难免会遇到乘方运算,比如面积的单位平方米,直接输入的话是m2,这显然是不对的,那么如何让2跑到m的右上角呢?第一步,输入想要的数字和单位,比如“100m2”,然后

    2023年02月05 203
  • 怎么调字体,win10修改系统默认字体

    在日常工作中,为了使我们的excel表美观,通常会做一些字体设置。win10修改系统默认字体,如下图(将“日期”设置为”2022-12-1”格式,将“放款金额”设置为“货币”格式,将“金额”占比改为“

    2023年02月08 233
  • 谷歌怎么截图,Google如何截图

    谷歌浏览器有一个隐藏在开发者工具中的功能,可以让你对任何网页进行全尺寸截图。此功能捕获整个页面,类似于滚动屏幕截图,Google如何截图,无需使用第三方扩展。,如何在Chrome中截取全尺寸屏幕截图首

    2023年02月05 211
  • 表格怎么插图片,WPS表格不跟着文字调整

    应该有不少小伙伴接收过上司或领导以图片格式发送过来的excel表格吧?并且还会要求我们将里面的内容整理为电子档,便于后期的内容编辑以及数据修改。而当你们收到这种任务时,是怎么去操作的呢?是不是大部分人

    2023年02月05 290
  • 怎么下载word

    电脑怎么免费使用word,现在我们需要查找论文相关的资料都是直接使用中国知网,那么知网的论文应该如何下载呢?怎样才能下载我们常用和熟悉的Word格式呢?比如我们打开知网后根据需要的资料关键字进行搜索,

    2023年02月13 249
  • 天文望远镜多少钱,1亿倍天文望远镜价格

    今天,1亿倍天文望远镜价格,通过小米雷军微博无意中翻到,雷总亲自站台了一款天文望远镜。微博原文为“买个望远镜,晚上拍月亮如何?”简简单单几个字,再配上小米有品在售的信息,另很多的粉丝也是不淡定了,对于

    2023年02月19 280
  • 100mb是多少流量,100MB是多少G

    在国内的三大运营商中,中国移动拥有最大的用户基数,同时也是遭用户吐槽最多的。在众多用户吐槽的槽点中,除了服务差、套路深、恶意扣费之外,还有资费高的问题,尤其是对于那个“曾经听说过但从没有办理过”的8元

    2023年03月13 266
  • 网商贷怎么关闭,怎么把支付宝网商贷图标去掉

    怎么把支付宝网商贷图标去掉,现在,支付宝的忠实用户不仅使用它来买东西、交水电费、查询社保,还用它来贷款。很多朋友在申请了支付宝中的网商贷以后又想取消。那么,支付宝如何取消网商贷呢?小编给大家介绍一下相

    2023年02月14 239
  • 开一个菜鸟驿站多少钱,快递驿站的十大坑

    开驿站最大的支出无疑就是人工和房租,如果你可以全职做,那肯定就大大节省了人工成本。其次,目前对于快递网点来讲,最认的是菜鸟驿站,这个毋庸置疑,为什么呢,因为菜鸟驿站有一套完整的客诉处理机制,相比其他品

    2023年03月14 285
关注微信