MySQL:在列列表中使用COUNT(column_name),在HAVING子句中再次使用。这是否导致COUNT(column_name)操作运行两次?

时间:2017-08-28 17:18:25

标签: mysql sql performance count aggregate

我很好奇在单个查询中两次使用COUNT(column_name)的性能。以下是有问题的查询:

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

威尔

COUNT(employee_name)

执行两次?此外,当我将来遇到这样的问题时,如何自行检查幕后发生的事情?

谢谢!

2 个答案:

答案 0 :(得分: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 vs 23字节)。这表明对于您的查询,计数在聚合期间完成两次。

答案 1 :(得分:-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?

我认为还有其他涉及非兰德案件的讨论。

原始问题使用COUNT(employee_name),在两种情况下都会提供相同的值。所以,你无法确定它是否被“评估”了两次。通过使用RAND(),很明显它会被重新评估。