测试数据
##学生表
CREATE TABLE student (
sid INT PRIMARY KEY auto_increment,
sname VARCHAR ( 20 ),
sage date,
ssex VARCHAR ( 2 ));
##老师表
CREATE TABLE teacher (
tid INT PRIMARY KEY auto_increment,
tname VARCHAR ( 20 ));
##分数表
CREATE TABLE course (
cid INT PRIMARY KEY auto_increment,
cname VARCHAR ( 20 ),
tid INT,
FOREIGN KEY ( tid ) REFERENCES teacher ( tid ));
##课程表
CREATE TABLE sc ( sid INT, cid INT, score INT );
INSERT INTO student
VALUES
( 1, '赵雷', '1990-01-01', '男' ),
( 2, '钱电', '1990-12-21', '男' ),
( 3, '孙风', '1990-05-20', '男' ),
( 4, '李云', '1990-08-06', '男' ),
( 5, '周梅', '1991-12-01', '女' ),
( 6, '吴兰', '1992-03-01', '女' ),
( 7, '郑竹', '1989-07-01', '女' ),
( 8, '王菊', '1990-01-20', '女' );
INSERT INTO teacher
VALUES
( 1, '张三' ),
( 2, '李四' ),
( 3, '王五' );
INSERT INTO course
VALUES
( 1, '数学', 2 ),
( 2, '语文', 1 ),
( 3, '英语', 3 );
INSERT INTO sc
VALUES
( 1, 1, 90 ),
( 1, 2, 80 ),
( 1, 3, 90 ),
( 2, 1, 70 ),
( 2, 2, 60 ),
( 2, 3, 80 ),
( 3, 1, 80 ),
( 3, 2, 80 ),
( 3, 3, 80 ),
( 4, 1, 50 ),
( 4, 2, 30 ),
( 4, 3, 20 ),
( 5, 1, 76 ),
( 5, 2, 87 ),
( 6, 1, 31 ),
( 6, 3, 34 ),
( 7, 2, 89 ),
( 7, 3, 98 );
查看Mysql语句的执行计划
在sql语句前加上Explain即可
查看执行计划
直接计划列属性分析
id
重要成度:重要
表明sql的执行顺序,有一下两个原则
1.数字大的先执行
2.数字一样顺序执行
在union的时候会出现id=null的情况 这步骤是最后执行的,合并两个结果集,去除重复值
select_type
重要程度:一般
SIMPLE:表示普通查询,查询中不包含子查询
PRIMARY:包含子查询,最外层查询标记为PRIMARY
SUBQUERY/MATERIALIZED:子查询本身被标记为SUBQUERY
UNION:union或者unionall的时候后面一个查询会被标记成union
UNIONRESULT:只有在union的时候会产生,union会去重,去重的步骤被标记成UNIONRESULT
table
重要程度:一般
操作的哪张表,有别名显示的是别名
由 ID 为 M,N 查询 union 产生的结果
由 ID 为 N 查询产生的结果
partitions
type
重要程度:极其重要
system:查看系统表少量数据,不需要IO,基本上我们写的sql不会到这个级别
const:常量连接,力所能及的最好优化
eq_ref:主键索引(primary key)或者非空唯一索引(unique not null)等值扫描
ref:非主键非唯一索引等值扫描
range:范围扫描
index:索引树扫描
ALL:全表扫描(full table scan)最差结果
-》从上到下是由快到慢
const:利用了主键索引,或者唯一索引
主键索引
给student表添加sname栏的唯一索引,查看查询sanme看执行计划
唯一索引
eq_ref:
join 查询,命中主键(primary key)或者非空唯一(unique not null)索引,等值连接;
主键联合查询
ref:
普通非唯一索引查询
普通非唯一索引查询
range
索引的范围查找
索引范围查找
index
索引全扫描
all
不用索引的查找都是all
执行计划 possible_keys
重要程度:一般
查询过程中有可能用到的索引。
执行计划 key
重要程度:重要
实际使用的索引,如果为 NULL ,则没有使用索引
rows
重要程度:一般
大概需要查找的行数
filtered
重要程度:一般
返回数据占读取数据的百分比,该值越大越好
Extra
重要程度:极其重要
Using filesort:MySQL 对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取。
Using temporary:使用临时表保存中间结果,也就是说 MySQL 在对查询结果排序时使用了临时表,常见于order by 或 group by。
Using index:表示 SQL 操作中使用了覆盖索引(Covering Index),避免了访问表的数据行,效率高。
Using index condition:表示 SQL 操作命中了索引,但不是所有的列数据都在索引树上,还需要访问实际的行记录。
Using where:表示 SQL 操作使用了 where 过滤条件。
Select tables optimized away:基于索引优化 MIN/MAX 操作或者 MyISAM 存储引擎优化 COUNT(*) 操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即可完成优化。
Using join buffer (Block Nested Loop):表示 SQL 操作使用了关联查询或者子查询,且需要进行嵌套循环计算。
using filesort : 没有索引条件进行排序的情况
外部文件排序-其中cid没有索引
属于糟糕情况之一
改进:排序列适当的添加索引
Using temporary
临时表存储
Extra 为 Using temporary 说明,需要建立临时表(temporary table)来暂存中间结果。
这类 SQL 语句性能较低,往往也需要进行优化。
典型的 group by 和 order by 同时存在,且作用于不同的字段时,就会建立临时表,以便计算出最终的结果集。
临时表存在两种引擎,一种是 Memory 引擎,一种是 MyISAM 引擎,如果返回的数据在 16M 以内(默认),且没有大字段的情况下,使用 Memory 引擎,否则使用 MyISAM 引擎
属于糟糕情况之一
改进:group by 后面字段适当的加索引
Using index
使用索引,属于好的情况
Using index condition
Extra 为 Using index condition 说明,确实命中了索引,但不是所有的列数据都在索引树上,还需要访问实际的行记录。
这类 SQL 语句性能也较高,但不如 Using index
Using where
使用了非索引的where条件
Select tables optimized away
比如上面的语句查询 id 的最大值,因为 id 是主键索引,根据 B+Tree 的结构,天然就是有序存放的,所以不需要等到执行阶段再进行计算,查询执行计划生成的阶段即可完成优化。
Using join buffer (Block Nested Loop)
Extra 为 Using join buffer (Block Nested Loop) 说明,需要进行嵌套循环计算。内层和外层的 type 均为 ALL,rows 均为4,需要循环进行4*4次计算。
这类 SQL 语句性能往往也较低,需要进行优化。
典型的两个关联表 join,关联字段均未建立索引,就会出现这种情况。常见的优化方案是,在关联字段上添加索引,避免每次嵌套循环计算。