官网介绍:Explain官网详情入口
目录
参数2:id:在一个大的查询语句中每个select关键字都对应一个唯一的id
参数3:select_type:SELECT关键字对应查询的类型,确定小查询在整个大查询中扮演了一个什么角色
参数6:possible_keys和key:可能用到的索引 和 实际上使用的索引
参数7:key_len:实际使用到的索引长度(即:字节数),帮你检查`是否充分的利用上了索引`,`当前key长度值越大越好`(主要针对于联合索引,有一定的参考意义)
参数8:ref:当使用索引列等值查询时,与索引列进行等值匹配的对象信息(比如只是一个常数或者是某个列)
参数10:filtered: 某个表经过搜索条件过滤后剩余记录条数的百分比
参数11:Extra:一些额外的信息,更准确的理解MySQL到底将如何执行给定的查询语句
用法
如果我们想看看某个查询的执行计划,就可以在具体的查询语句前面加一个EXPLAIN或者DESCRIBE,可用于优化sql语句;
开胃例
1.删除id为2的学生信息,sql语句头部添加关键字EXPLAIN查看该sql语句的执行计划
EXPLAIN DELETE FROM student_info WHERE id = 2;
2.执行结果
参数详解
- partitions -- 匹配的分区信息
- type -- 针对单表的访问方法
- possible_keys -- 可能用到的索引
- key -- 实际用到的索引
- key_len -- 实际使用到的索引长度
- ref -- 当使用索引列等值查询时,与索引列进行等值匹配的对象信息
- rows -- 预估的需要读取的记录条数
- filtered -- 某个表经过搜索条件过滤后剩余记录条数的百分比
- extra -- 额外信息
3.查看id为2的学生信息
SELECT * FROM student_info WHERE id = 2;
4.执行可以获取结果
结论:EXPLAIN不对表产生实际操作
Explain参数(重点!!!)
1.我们先使用以下存储函数创建两个表s1、s2(建表之前记得切换数据库哦)
#创建表
CREATE TABLE s1 (
id INT AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
INDEX idx_key1 (key1),
UNIQUE INDEX idx_key2 (key2),
INDEX idx_key3 (key3),
INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;
CREATE TABLE s2 (
id INT AUTO_INCREMENT,
key1 VARCHAR(100),
key2 INT,
key3 VARCHAR(100),
key_part1 VARCHAR(100),
key_part2 VARCHAR(100),
key_part3 VARCHAR(100),
common_field VARCHAR(100),
PRIMARY KEY (id),
INDEX idx_key1 (key1),
UNIQUE INDEX idx_key2 (key2),
INDEX idx_key3 (key3),
INDEX idx_key_part(key_part1, key_part2, key_part3)
) ENGINE=INNODB CHARSET=utf8;
2.使用函数插入数据(这里的存储函数类似Java的循环结构)
#创建存储函数:
DELIMITER //
CREATE FUNCTION rand_string1(n INT)
RETURNS VARCHAR(255) #该函数会返回一个字符串
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str =CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i + 1;
END WHILE;
RETURN return_str;
END //
DELIMITER ;
SET GLOBAL log_bin_trust_function_creators=1;
#创建存储过程:
DELIMITER //
CREATE PROCEDURE insert_s1 (IN min_num INT (10),IN max_num INT (10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO s1 VALUES(
(min_num + i),
rand_string1(6),
(min_num + 30 * i + 5),
rand_string1(6),
rand_string1(10),
rand_string1(5),
rand_string1(10),
rand_string1(10));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER ;
DELIMITER //
CREATE PROCEDURE insert_s2 (IN min_num INT (10),IN max_num INT (10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO s2 VALUES(
(min_num + i),
rand_string1(6),
(min_num + 30 * i + 5),
rand_string1(6),
rand_string1(10),
rand_string1(5),
rand_string1(10),
rand_string1(10));
UNTIL i = max_num
END REPEAT;
COMMIT;
END //
DELIMITER ;
#调用存储过程
CALL insert_s1(10001,10000);
CALL insert_s2(10001,10000);
3.查看我们插入的数据总量
SELECT COUNT(*) AS s1_count,COUNT(*) AS s2_count FROM s1,s2;
两个表各插入了一万条数据如下显示:
数据创建好了,下面来揭开Explain参数的神秘面纱吧~~
参数1:table:表名
查询的每一行记录都对应着一个单表
例子1:单表查询
EXPLAIN SELECT * FROM s1;
执行结果:table = s1
例子2(s1:驱动表 s2:被驱动表):
EXPLAIN SELECT * FROM s1 INNER JOIN s2;
执行结果:table = s1、s2
参数2:id:在一个大的查询语句中每个select关键字都对应一个唯一的id
- 单表查询
SELECT * FROM s1 WHERE key1 = 'a';
结果:因为只涉及到一张表,因此id为1
- 连表查询
EXPLAIN SELECT * F