2013-09-30 1 views
0

У меня есть простой запрос SQL:запросов с WHERE и HAVING

SELECT id, title, resum 
FROM film 
WHERE id = 56 ; 

Время отклика для этого запроса почти равен 0,0009 сек

В то время как тот же запрос, с помощью предложения HAVING:

SELECT id, title, resum 
FROM film 
HAVING id =56 ; 

Дайте такое большое время отклика, с 1-м запросом (0,0049 сек).

1-й запрос более оптимизирован, но, почему? Можете ли вы рассказать мне причину, которая вызывает эту большую разницу?

С наилучшими пожеланиями.

ответ

1

Сначала давайте укажем самое главное: ваш второй запрос не является допустимым 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» и, таким образом, он просто должен прочитать одну строку, в результате чего значительно более быстрый отклик.