MySQL5.7union all用法的黑科技
union all在MySQL5.6下的表现
Part1:MySQL5.6.25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@HE1 ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connectionid is 2
Server version: 5.6.25-log MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type'help;' or'\h' for help. Type'\c' toclear the current input statement.
mysql>select version();
+------------+
| version() |
+------------+
| 5.6.25-log |
+------------+
1 rowin set (0.26 sec)
mysql> explain (select id from helei order byid) union all (select id from t whereid=0 order byid);
+----+--------------+------------+-------+---------------+--------+---------+------+------+-----------------+
|id | select_type | table |type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+---------------+--------+---------+------+------+-----------------+
| 1 | PRIMARY | helei | index | NULL | idx_c1 | 4 | NULL | 5219 | Using index |
| 2 | UNION | t | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
| NULL | UNION RESULT | | ALL | NULL | NULL | NULL | NULL | NULL | Using temporary |
+----+--------------+------------+-------+---------------+--------+---------+------+------+-----------------+
3 rowsin set (0.00 sec)
可以看出,在MySQL5.6版本中,执行结果如下图所示:
从执行计划来看,是把helei表的查询结果和t表的查询结果合并在了一张临时表里,然后输出给客户端。
union all在MySQL5.7/MariaDB10.1下的表现
Part1:MySQL5.7.15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@HE1 ~]# mysql -uroot -p
Enterpassword:
Welcometo the MySQL monitor. Commandsend with ;or \g.
Your MySQLconnection idis 8
Server version: 5.7.15-log MySQL Community Server (GPL)
Copyright (c) 2000, 2016, Oracleand/or its affiliates.All rights reserved.
Oracleis a registered trademarkof Oracle Corporationand/or its
affiliates. Other names may be trademarksof their respective
owners.
Type'help;' or '\h' for help. Type'\c' to clear thecurrent input statement.
mysql>select version();
+------------+
| version() |
+------------+
| 5.7.15-log |
+------------+
1 rowin set (0.00 sec)、
mysql> explain (select idfrom heleiorder by id)union all (select idfrom twhere id=0order by id);
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
| id | select_type |table | partitions | type | possible_keys |key | key_len | ref |rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
| 1 |PRIMARY | helei |NULL |index |NULL | idx_c1 | 4 |NULL | 5212 | 100.00 | Usingindex |
| 2 |UNION | t |NULL |ALL |NULL |NULL |NULL |NULL | 1 | 100.00 | Usingwhere |
+----+-------------+-------+------------+-------+---------------+--------+---------+------+------+----------+-------------+
2rows in set, 1 warning (0.00 sec)
可以看出,在MySQL5.7版本中,执行结果如下图所示:
Part2:MariaDB10.1.16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@HE3 ~]# /usr/local/mariadb/bin/mysql -uroot -S /tmp/mariadb.sock
Welcometo the MariaDB monitor. Commandsend with ;or \g.
Your MariaDBconnection idis 7
Server version: 10.1.16-MariaDB MariaDB Server
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Aband others.
Type'help;' or '\h' for help. Type'\c' to clear thecurrent input statement.
MariaDB [(none)]>
MariaDB [helei]> explain (select idfrom heleiorder by id)union all (select idfrom twhere id=0order by id);
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------------+
| id | select_type |table | type | possible_keys |key | key_len | ref |rows | Extra |
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------------+
| 1 |PRIMARY | helei |index |NULL | idx_c1 | 4 |NULL | 5198 | Usingindex |
| 2 |UNION | t |ALL |NULL |NULL |NULL |NULL | 1 | Usingwhere |
+------+-------------+-------+-------+---------------+--------+---------+------+------+-------------+
2rows in set (0.00 sec)
可以看出在MariaDB10.1中,执行结果如下图所示:
从执行结果看,无论是MySQL5.7还是MariaDB10.1,都没有创建临时表,按照顺序,helei表的查询结果首先输出到客户端,然后t表的查询结果再输出到客户端。
本文中的优化只针对union all,对union和在最外层使用order by无效。如下图是所示:
——总结——
在MySQL5.7/MariaDB10.1中,union all不再创建临时表,这样在联合查询时会减少I/O开销,在MySQL5.5/5.6中则不具备这一特性。由于笔者的水平有限,编写时间也很仓促,文中难免会出现一些错误或者不准确的地方,不妥之处恳请读者批评指正。
结束语