Сначала давайте укажем самое главное: ваш второй запрос не является допустимым 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 с примерно 1,2 миллионами строк. Запрос 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 | |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------+
Вы видите, что в поле «ключ» указано «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 | |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
С другой стороны, EXPLAIN
для WHERE
говорит нам, что он использует индекс «PRIMARY» и, таким образом, он просто должен прочитать одну строку, в результате чего значительно более быстрый отклик.