1. 简单 select 查询,name是普通索引(非唯一索引) mysql> explain select * from film where name = "film1"; +----+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+ | 1 | SIMPLE | film | ref | idx_name | idx_name | 33 | const | 1 | Using where; Using index | +----+-------------+-------+------+---------------+----------+---------+-------+------+--------------------------+
2.关联表查询,idx_film_actor_id是film_id和actor_id的联合索引,这里使用到了film_actor的左边前缀film_id部分。 mysql> explain select * from film left join film_actor on film.id = film_actor.film_id; +----+-------------+------------+-------+-------------------+-------------------+---------+--------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+-------+-------------------+-------------------+---------+--------------+------+-------------+ | 1 | SIMPLE | film | index | NULL | idx_name | 33 | NULL | 3 | Using index | | 1 | SIMPLE | film_actor | ref | idx_film_actor_id | idx_film_actor_id | 4 | test.film.id | 1 | Using index | +----+-------------+------------+-------+-------------------+-------------------+---------+--------------+------+-------------+
**ref_or_null**:类似ref,但是可以搜索值为 NULL 的行。
1 2 3 4 5 6
mysql> explain select * from film where name = "film1" or name is null; +----+-------------+-------+-------------+---------------+----------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------------+---------------+----------+---------+-------+------+--------------------------+ | 1 | SIMPLE | film | ref_or_null | idx_name | idx_name | 33 | const | 2 | Using where; Using index | +----+-------------+-------+-------------+---------------+----------+---------+-------+------+--------------------------+
mysql> explain select id from film order by id; +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+ | 1 | SIMPLE | film | index | NULL | PRIMARY | 4 | NULL | 3 | Using index | +----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
**Using where**:mysql 服务器将在存储引擎检索行后再进行过滤。就是先读取整行数据,再按 where 条件进行检查,符合就留下,不符合就丢弃。
1 2 3 4 5 6
mysql> explain select * from film where id > 1; +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+ | 1 | SIMPLE | film | index | PRIMARY | idx_name | 33 | NULL | 3 | Using where; Using index | +----+-------------+-------+-------+---------------+----------+---------+------+------+--------------------------+
1. actor.name没有索引,此时创建了张临时表来distinct mysql> explain select distinct name from actor; +----+-------------+-------+------+---------------+------+---------+------+------+-----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+-----------------+ | 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 2 | Using temporary | +----+-------------+-------+------+---------------+------+---------+------+------+-----------------+
2. film.name建立了idx_name索引,此时查询时extra是using index,没有用临时表 mysql> explain select distinct name from film; +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | film | index | idx_name | idx_name | 33 | NULL | 3 | Using index | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+
**Using filesort**:mysql 会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。此时 mysql 会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1. actor.name未创建索引,会浏览actor整个表,保存排序关键字name和对应的id,然后排序name并检索行记录 mysql> explain select * from actor order by name; +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+ | 1 | SIMPLE | actor | ALL | NULL | NULL | NULL | NULL | 2 | Using filesort | +----+-------------+-------+------+---------------+------+---------+------+------+----------------+
2. film.name建立了idx_name索引,此时查询时extra是using index mysql> explain select * from film order by name; +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ | 1 | SIMPLE | film | index | NULL | idx_name | 33 | NULL | 3 | Using index | +----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+