MySql学习笔记(八):explain之extra
admin
2023-04-18 13:03:59
0

extra主要有是那种情况:Using index、Using filesort、Using temporary、Using where

Using where无需多说,就是使用了where筛选条件。

数据准备:

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

1、Using index

表示在查询中使用了覆盖索引,避免了扫描表的数据行。

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为例。

当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

2、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优化器只能自己进行排序,这种情况会大大降低性能,不可取。

3、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意味着产生了临时表存储中间结果并且最后删掉了该临时表,这个过程很消耗性能。

相关内容

热门资讯

“特高课”再现?日本强推“国家... 无视反对战争正义呼声 复刻战前军国主义体制日本强推“国家情报局”引发广泛担忧和批评(国际视点)本报记...
6G相比5G不只是速度更快 将...   6G相比5G不只是速度更快  【6G相比5G不只是速度更快】7月28日,相比5G,6G不仅是速度...
趣享夏日消保同行 泰康人寿深圳...   7月12日,为落实2026年“7·8全国保险公众宣传日”工作部署,泰康人寿深圳分公司结合三十周年...
泰康人寿深圳分公司联合泰康养老...   为深入践行金融工作的政治性、人民性,切实守护新就业群体的财产安全,7月23日下午,在深圳市居民金...
中牟改善买房必看:三代宅和四代... 准备在中牟买改善房的人,十有八九会纠结同一个问题:到底是买传统的第三代住宅,还是紧跟郑州置业主流买第...
徐巧芯剖析赖清德:最怕自己丢掉... 海峡导报综合报道 大罢免投票一周年纪念活动26日举行,台北市长蒋万安出席并怒轰,民进党一年过后仍没有...
中国红十字会总会紧急向广东调拨... 记者从中国红十字会总会了解到,针对台风“红霞”给广东造成的灾情,中国红十字会总会启动四级应急响应,紧...
这些少年,正被“毒蛋”围猎 李梦抽了几口电子烟,吐出了白色的烟雾,有一股浓烈的水果香味。随后,她看着自己握电子烟的手,跟身边人说...
蒋万安号召“倒阁”,卢秀燕认为... 海峡导报综合报道 台北市长蒋万安27日抛出震撼议题,表示多名民代向他提议推动“倒阁”,要求台行政机构...
特朗普将在白宫会见两位重要客人 俄乌战争仍未结束,美伊冲突又有升级风险。在此背景下,美国总统特朗普将在白宫接见乌克兰和以色列领导人。...