首先,让我们声明最重要的一点:您的第二个查询不是有效的 SQL 查询,因为它使用了 MySQL GROUP BY extensions。当您使用
关闭此 MySQL 扩展时
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
然后你会得到这样的错误:
ERROR 1463 (42000): non-grouping field 'id' is used in HAVING clause
所以,你真的应该使用WHERE 子句。
但现在是您的实际问题。我从您的测量中假设“id”字段上有一个索引。因为HAVING 在分组数据上工作(应该工作),所以没有它可以使用的索引。我这里有一个 MySQL 表,大约有 120 万行。对索引整数字段的 HAVING 查询在第一次运行时需要 16 秒,在连续调用时仍然需要大约 0.6 秒,而使用 WHERE 的查询只需要 0.04 秒。
使用EXPLAIN,MySQL 会告诉你它不使用索引:
EXPLAIN SELECT id, title, resum FROM film HAVING id =56;
例如,下面是EXPLAIN 对我的表的查询的结果:
mysql> EXPLAIN SELECT id, Title FROM `test` HAVING id = 4374354;
+----+-------------+----------+------+---------------+------+---------+------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------+
| 1 | SIMPLE | test | ALL | NULL | NULL | NULL | NULL | 1201750 | |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------+
你看,“key”字段的状态是“NULL”,告诉你没有使用任何索引。相反,“rows”字段告诉您,MySQL 遍历 1201750(所有)行。
mysql> EXPLAIN SELECT id, Title FROM `test` WHERE id = 4374354;
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | test | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
另一方面,WHERE 的 EXPLAIN 告诉我们,它使用“PRIMARY”索引,因此它只需要读取一行,从而获得更快的响应。