extra主要有是那種狀況:Using index、Using filesort、Using temporary、Using wherejava
Using where無需多說,就是使用了where篩選條件。mysql
數據準備:sql
CREATE TABLE `t_blog` ( `id` int(11) NOT NULL auto_increment, `title` varchar(50) default NULL, `typeId` int(11) default NULL, `a` int(11) default '0', PRIMARY KEY (`id`), KEY `index_1` (`title`,`typeId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
一、Using indexmysql優化
表示在查詢中使用了覆蓋索引,避免了掃描表的數據行。ide
mysql> EXPLAIN select title from t_blog; +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ | 1 | SIMPLE | t_blog | index | NULL | index_1 | 158 | NULL | 7 | Using index | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ 1 row in set
已知title字段是index_1索引的一部分,上條sql只查詢title字段,只會掃描索引文件而不會掃描表的全部數據行,在extra列中,出現了Using index。性能
mysql> EXPLAIN select * from t_blog; +----+-------------+--------+------+---------------+------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+---------------+------+---------+------+------+-------+ | 1 | SIMPLE | t_blog | ALL | NULL | NULL | NULL | NULL | 7 | | +----+-------------+--------+------+---------------+------+---------+------+------+-------+ 1 row in set
上條語句中,除了查詢已經加了索引的字段,還查詢了沒有加索引的字段【a】,致使掃描了表的數據行,所以,extra列中沒有出現Using index。優化
當只出現Using index,沒出現Using where時,表示索引用於讀取數據,以第一條sql爲例。blog
當Using index 和 Using where同時出現時,表示索引用於查找動做,例如:排序
mysql> EXPLAIN select title from t_blog where title = 'java'; +----+-------------+--------+------+---------------+---------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+---------------+---------+---------+-------+------+--------------------------+ | 1 | SIMPLE | t_blog | ref | index_1 | index_1 | 153 | const | 1 | Using where; Using index | +----+-------------+--------+------+---------------+---------+---------+-------+------+--------------------------+ 1 row in set
二、Using filesort索引
Using filesort一般出如今order by,當試圖對一個不是索引的字段進行排序時,mysql就會自動對該字段進行排序,這個過程就稱爲「文件排序」
mysql> EXPLAIN select * from t_blog order by title; +----+-------------+--------+-------+---------------+---------+---------+------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------+ | 1 | SIMPLE | t_blog | index | NULL | index_1 | 158 | NULL | 7 | | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------+ 1 row in set
已知title是index_1索引中的第一列索引,因此單獨使用時索引生效,在排序時根據索引排序,不會產生文件排序。
mysql> EXPLAIN select * from t_blog order by typeId; +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ | 1 | SIMPLE | t_blog | ALL | NULL | NULL | NULL | NULL | 7 | Using filesort | +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ 1 row in set
雖然typeId是index_1索引的第二列,但因爲缺失第一列,因此索引失效。在排序時沒法根據索引排序,故mysql會自動進行排序,產生文件排序。
mysql> EXPLAIN select * from t_blog order by a; +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ | 1 | SIMPLE | t_blog | ALL | NULL | NULL | NULL | NULL | 7 | Using filesort | +----+-------------+--------+------+---------------+------+---------+------+------+----------------+ 1 row in set
字段a上沒有任何索引,因此在排序時沒法根據索引排序,所以產生文件排序。
Using filesort出現的狀況:排序時沒法根據索引進行排序,mysql優化器只能本身進行排序,這種狀況會大大下降性能,不可取。
三、Using temporary
表示在查詢過程當中產生了臨時表用於保存中間結果。mysql在對查詢結果進行排序時會使用臨時表,常見於group by。
group by的實質是先排序後分組,同order by同樣,group by和索引息息相關。
試圖對一個沒有索引的字段進行分組,會產生臨時表:
mysql> EXPLAIN select title from t_blog group by typeId; +----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------------------+ | 1 | SIMPLE | t_blog | index | NULL | index_1 | 158 | NULL | 7 | Using index; Using temporary; Using filesort | +----+-------------+--------+-------+---------------+---------+---------+------+------+----------------------------------------------+ 1 row in set
對一個有索引的字段進行分組就不會產生臨時表:
mysql> EXPLAIN select title from t_blog group by title,typeId; +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ | 1 | SIMPLE | t_blog | index | NULL | index_1 | 158 | NULL | 7 | Using index | +----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ 1 row in set
當order by子句和group by子句的字段相同時不會產生臨時表:
mysql> explain select * from t_blog b left join t_type t on b.typeId = t.id group by b.id order by b.id; +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------+ | 1 | SIMPLE | b | index | NULL | PRIMARY | 4 | NULL | 7 | | | 1 | SIMPLE | t | eq_ref | PRIMARY | PRIMARY | 4 | blog.b.typeId | 1 | | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-------+ 2 rows in set
當order by子句和group by子句的字段不一樣時就會產生臨時表:
mysql> explain select * from t_blog b left join t_type t on b.typeId = t.id group by b.id order by b.title; +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-----------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-----------------+ | 1 | SIMPLE | b | index | NULL | index_1 | 158 | NULL | 7 | Using temporary | | 1 | SIMPLE | t | eq_ref | PRIMARY | PRIMARY | 4 | blog.b.typeId | 1 | | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+-----------------+ 2 rows in set
當時用left join時,若order by子句和group by子句都來自於從表時會產生臨時表:
mysql> explain select * from t_blog b left join t_type t on b.typeId = t.id group by t.id order by t.id; +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ | 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 7 | Using temporary; Using filesort | | 1 | SIMPLE | t | eq_ref | PRIMARY | PRIMARY | 4 | blog.b.typeId | 1 | | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ 2 rows in set
mysql> explain select * from t_blog b left join t_type t on b.typeId = t.id group by t.id order by t.name; +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ | 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 7 | Using temporary; Using filesort | | 1 | SIMPLE | t | eq_ref | PRIMARY | PRIMARY | 4 | blog.b.typeId | 1 | | +----+-------------+-------+--------+---------------+---------+---------+---------------+------+---------------------------------+ 2 rows in set
出現Using temporary意味着產生了臨時表存儲中間結果而且最後刪掉了該臨時表,這個過程很消耗性能。