假设我有如下查询:
SELECT message.mid
FROM message
WHERE message.mid <= 100
据我所知,如果将查询更改为以下内容,由于未扩展列,它将执行得更快。
SELECT COUNT(message.mid)
FROM message
WHERE message.mid <= 100
但是下面的查询会有相同的好处吗?还会那么快吗?
SELECT COUNT(*)
FROM (
SELECT message.mid,
message.something,
message.something2,
message.something3,
FROM message
WHERE message.mid <= 100
) AS A
答案 0 :(得分:2)
We can ask MySQL what it will do。这是5.7。
mysql> explain SELECT COUNT(*) FROM ( SELECT message.mid FROM message WHERE message.mid <= 100
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | message | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 100 | 100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
mysql> explain SELECT count(message.mid) FROM message WHERE message.mid <= 100;
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | message | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 100 | 100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
看起来一样。 MySQL优化了子查询。
这是一个示例,说明我们在MySQL无法优化子查询的情况下看到的内容。
mysql> explain SELECT * FROM ( SELECT message.mid FROM message where mid < 100 group by mid) m;
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 99 | 100.00 | NULL |
| 2 | DERIVED | message | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 99 | 100.00 | Using where; Using index |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
"Optimizing Derived Tables and View References"举例说明了此优化的工作原理。
示例1:
SELECT * FROM (SELECT * FROM t1) AS derived_t1;
合并后,该查询的执行方式类似于:
SELECT * FROM t1;
该页面概述了MySQL用于提高子查询效率的其他许多优化技巧。
答案 1 :(得分:1)
COUNT(*)
说要计算行数。
COUNT(x)
表示对x IS NOT NULL
处的行进行计数。因此,速度稍慢,并且答案可能有所不同。
SELECT mid
(相对于SELECT COUNT(...)
)-速度慢且体积大。它返回的是mid
的所有值,而不仅仅是一个数字。
SELECT COUNT(..) FROM ( SELECT ... )
-慢得多(在旧的MySQL版本中),因为它必须使用子查询的结果生成一个临时表。另外,COUNT
仅收集一个简单的数字;子查询正在收集很多行。
如果为mid
编制了索引(包括PRIMARY KEY
,则WHERE mid <= 100
是对索引(或表)的“范围”扫描。也就是说,它仅触及部分行。
如果未为mid
编制索引,则将扫描整个表格-因此速度较慢。