2017-08-28 59 views
0

我很好奇在單個查詢中兩次使用COUNT(column_name)的性能。這是有問題的查詢:MySQL:在列表中使用COUNT(column_name),並再次在HAVING子句中使用。這是否會導致COUNT(column_name)操作運行兩次?

SELECT 
    employee_name, 
    COUNT(employee_name) 
FROM 
    employee 
GROUP BY 
    employee_name 
HAVING 
    COUNT(employee_name) > 1; 

COUNT(employee_name) 

執行兩次?此外,如果我將來有這樣的問題,我該如何檢查封面下發生的事情?

謝謝!

+0

使用'COUNT(*)',除非你想避免計算'employee_name IS NULL'的行數。 –

回答

-1

選擇任何方便的表,這樣做:

mysql> SELECT RAND() AS r FROM canada HAVING r < 0.1 limit 11; 
+-----------------------+ 
| r      | 
+-----------------------+ 
| 0.6982369559800596 | 
| 0.33121224616767114 | 
| 0.3811396559524719 | 
| 0.4718028721136999 | 

參見:

Using `rand()` with `having`

Is there Performance related difference in using aggregate function in ORDER BY clause and alias of aggregate function?

而且我認爲有涉及非-RAND情況等進行討論。

原始問題使用COUNT(employee_name),它在兩種情況下都提供相同的值。所以,你無法確定它是否被「評估過」兩次。通過使用RAND(),它變得清楚,它被重新評估。

+1

這不是一個很好的例子IMO,因爲在你的查詢中'HAVING'真的表現得像'WHERE'。 MySQL的一個特點是'HAVING'已經以這種方式超載了。 –

+0

@TimBiegeleisen - 我的觀點是,儘管有別名,但它顯然正在重新評估。 –

+0

好點+1。我會更新我的答案,並引用你的意見。但無論如何,我認爲OP主要是在「GROUP BY」查詢的背景下提問。 –

2

您可以使用優化程序跟蹤獲取有關優化程序如何執行查詢以及原因的更多信息。對於這種特殊的情況下,跟蹤不明確告訴多少次計數的計算方式,但我們可以得到有關用於執行聚合的臨時表的信息:


mysql> SET optimizer_trace='enabled=on';            
Query OK, 0 rows affected (0,00 sec) 

mysql> SELECT c2, COUNT(c2) FROM temp GROUP BY c2 HAVING COUNT(c2) > 1; 
+------+-----------+ 
| c2 | COUNT(c2) | 
+------+-----------+ 
| 1 |   2 | 
| 2 |   2 | 
+------+-----------+ 
2 rows in set (0,00 sec) 

mysql> SELECT trace->'$.steps[*].join_execution.steps[*].creating_tmp_table' 
    -> FROM information_schema.optimizer_trace; 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'                            | 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| [{"tmp_table_info": {"table": "intermediate_tmp_table", "location": "memory (heap)", "key_length": 5, "row_length": 23, "unique_constraint": false, "row_limit_estimate": 729444}}] | 
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0,01 sec) 

mysql> SELECT c2, COUNT(c2) AS c FROM temp GROUP BY c2 HAVING c > 1; 
+------+---+ 
| c2 | c | 
+------+---+ 
| 1 | 2 | 
| 2 | 2 | 
+------+---+ 
2 rows in set (0,00 sec) 

mysql> SELECT trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'   -> FROM information_schema.optimizer_trace; 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| trace->'$.steps[*].join_execution.steps[*].creating_tmp_table'                              | 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| [{"tmp_table_info": {"table": "intermediate_tmp_table", "location": "memory (heap)", "key_length": 5, "row_length": 14, "unique_constraint": false, "row_limit_estimate": 1198372}}] | 
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0,00 sec) 

對於上面我們看到,當使用別名而不是重複COUNT表達式時,臨時表的行大小更小(14對23字節)。這表示對於您的查詢,在聚合期間計數已完成兩次。

相關問題