delimiter //
drop procedure if exists produce_data//
create procedure produce_data()
begin
declare i int default 0;
drop table if exists a;
drop table if exists b;
drop table if exists c;
create table a(id int not null,name varchar(32));
create table b(id int not null,name varchar(32));
create table c(id int not null,name varchar(32));
set i = 1;
while i <= 4 do
insert into a(id,name) values(i, concat('name', i));
set i = i + 1;
end while;
set i = 3;
while i <= 6 do
insert into b(id,name) values(i, concat('name', i));
set i = i + 1;
end while;
set i = 5;
while i <= 8 do
insert into c(id,name) values(i, concat('name', i));
set i = i + 1;
end while;
end//
call produce_data()//
delimiter ;
mysql> select * from a;
+----+-------+
| id | name |
+----+-------+
| 1 | name1 |
| 2 | name2 |
| 3 | name3 |
| 4 | name4 |
+----+-------+
mysql> select * from b;
+----+-------+
| id | name |
+----+-------+
| 3 | name3 |
| 4 | name4 |
| 5 | name5 |
| 6 | name6 |
+----+-------+
mysql> select * from c;
+----+-------+
| id | name |
+----+-------+
| 5 | name5 |
| 6 | name6 |
| 7 | name7 |
| 8 | name8 |
+----+-------+
mysql> explain select * from a;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 4 | |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
id 全部相同
mysql> explain select * from a,b,c
-> where a.id = b.id and a.id = c.id;
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
| 1 | SIMPLE | a | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer |
| 1 | SIMPLE | c | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer |
+----+-------------+-------+------+---------------+------+---------+------+------+--------------------------------+
id 相同,顺序由上至下。 即 a -> b -> c
id 全不相同
mysql> explain select * from b
-> where b.id = (
-> select id from a
-> where id =
-> (select id from c
-> where name = 'name99'));
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | PRIMARY | b | ALL | NULL | NULL | NULL | NULL | 4 | Using where |
| 2 | SUBQUERY | a | ALL | NULL | NULL | NULL | NULL | 4 | Using where |
| 3 | SUBQUERY | c | ALL | NULL | NULL | NULL | NULL | 4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
id 不同,值越大,越先被操作。即 c -> a -> b
前两种情况同时存在
mysql> explain select * from (
-> select id from b) bb, c
-> where bb.id = c.id;
+----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+
| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 4 | |
| 1 | PRIMARY | c | ALL | NULL | NULL | NULL | NULL | 4 | Using where; Using join buffer |
| 2 | DERIVED | b | ALL | NULL | NULL | NULL | NULL | 4 | |
+----+-------------+------------+------+---------------+------+---------+------+------+--------------------------------+
b -> derived2 -> c
常见值:SIMPLE、PRIMARY、SUBQUERY、DERIVED、UNION、UNION RESULT
SIMPLE:简单的 select 查询,查询不包含子查询或UNION;
PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为 PRIMARY;
SUBQUERY:在 SELECT 或 WHERE 列表中包含的子查询;
DERIVED:在 FROM 列表中包含的子查询被标记为 DERIVED;
UNION:若第二个SELECT出现在UNION之后,则标记为UNION;若UNION包含在FROM子句的子查询种,外层SELECT则是DERIVED;(被 UNION 的 select )
UNION RESULT:从 UNION 表获取结果的SELECT。
system,表只有一行记录(等于系统表) ,是 const 类型的特例,基本看不到。经过测试,甚至,只有一条记录也并非是 system,但是以下情况可以:
mysql> explain select t.id, t.name from (select * from a where id = 2) t;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
| 1 | PRIMARY | | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | a | const | PRIMARY | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------+
const,表示通过索引一次就找到了,const 用于比较primary key 或 unique 索引。因为只匹配一行数据,所以很快。如果将主键置于where列表中,MySQL 就能将该查询转换为一个常量。
eq_ref,唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描。
ref,非唯一性索引扫描,返回匹配某个单独值的所有行。
create index idx_name on a(name);
mysql> explain select * from a where name = 'name1';
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | a | ref | idx_name | idx_name | 35 | const | 1 | Using where |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
range,只检索给定范围的行,使用一个索引来选择行。key 列会显示使用了哪个索引。
常见于 where 语句使用 between、<、>、in 等查询。
alter table a add primary key(id);
mysql> explain select * from a where id > 2 and id < 5;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | a | range | PRIMARY | PRIMARY | 4 | NULL | 1 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
index,index 与 all 尽管都是遍历,但是 index 遍历的是索引树,而且索引文件通常比数据文件小。
mysql> explain select id from a;
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
| 1 | SIMPLE | a | index | NULL | idx_name | 35 | NULL | 4 | Using index |
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
all,全表扫描。