假设我有如下查询:
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发布于 2018-11-14 20:22:45
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,那么整个表将被扫描--因此速度更慢。
发布于 2018-11-13 18:20:09
我们可以问MySQL它会做什么。这是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 |
+----+-------------+------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+“优化派生表和视图引用”有这种优化工作的例子。
示例1: 选择* FROM (SELECT * t1)作为derived_t1; 通过合并,该查询的执行方式类似于: 从t1中选择*;
该页面概述了MySQL为提高子查询效率而使用的许多其他优化技巧。
https://stackoverflow.com/questions/53286825
复制相似问题