2013-09-30 30 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 ; 

給出如此大的響應時間與第一個請求(0.0049秒)一起完成。

第一個請求更優化,但是,爲什麼? 你能告訴我造成這種巨大差異的原因嗎?

最好的問候。

回答

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對分組數據有效(應該可以),所以沒有可以使用的索引。我在這裏有一個約有120萬行的MySQL表。 A 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 |  | 
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+ 

在另一方面,對於EXPLAINWHERE告訴我們,它使用了「主要」指標,因此它只是讀取單行,導致更快的響應。