说我有这个问题:
private static ApiFuture<String> publishMessage(Publisher publisher, ByteString message)
throws Exception {
// convert message to bytes
PubsubMessage pubsubMessage =
PubsubMessage.newBuilder().setData(message).build();
return publisher.publish(pubsubMessage);
}
我的查询中有两次SELECT CompanyId, COUNT(*) as Total
FROM Customer
GROUP BY CompanyId
HAVING COUNT(*) > 100
。这是否意味着COUNT(*)
执行了两次?
这是一个简单的例子,但是当我有一个更复杂的计算(类似COUNT
)时,我担心它可能会影响性能。或者任何性能影响是否可以忽略不计?
我使用的是MS SQL 2012,但不能SUM(Weight) / COUNT(*)
。
答案 0 :(得分:3)
如果您对查询的处理方式有兴趣,请熟悉execution plans以及如何阅读它们。以下所有内容都是通过实验确定的。
聚合不会被计算多次,但涉及它们的表达式是。考虑:
SELECT CompanyId, SUM(Weight) / COUNT(*)
FROM Customer
GROUP BY CompanyId
HAVING SUM(Weight) / COUNT(*) > 100
SUM(Weight)
和COUNT(*)
将只计算一次,但除法将执行两次(一次过滤,一次选择)。当然,这对性能没有可测量的影响 - 关键是它最大限度地减少了必须通过所有数据的次数。
这意味着,即使您的HAVING
与SELECT
列表完全不同,该表仍会只扫描一次并汇总一次:
SELECT CompanyId, MAX(Weight), MIN(Weight), COUNT(*) as Total
FROM Customer
GROUP BY CompanyId
HAVING MAX(Weight) > 2 * MIN(Weight) AND AVG(Weight) > 0.5
此处有四个聚合:MAX(Weight)
,MIN(Weight)
,AVG(Weight)
和COUNT(*)
。 1 优化器将计算所有这些聚合传递,按CompanyId
对整体进行分组,应用HAVING
过滤器,然后选择所需的结果。 2
免责声明:与关于优化程序所做的所有声明一样,所有这些都可能在SQL Server的任何版本中发生变化,并且可能因跟踪标记,统计信息,索引和特定查询的细节而有所不同。对于SQL Server 2012和2016,至少对于两个特定的数据库,至少在索引不起作用的情况下,情况就是如此。
AVG
实际上并不是一个聚合物;在内部,优化器将其扩展为SUM / COUNT(*)
,并进行检查以防止除以零。因此,聚合实际上是MAX
,MIN
,SUM
和COUNT
。答案 1 :(得分:1)
尽管决定权取决于查询优化程序,但COUNT(*)
将完成两次。
而且,这几乎没有任何区别。
聚合数据所花费的精力在于移动数据,而不是在聚合函数中,尤其是像COUNT(*)
这样的函数。一些聚合函数更昂贵(COUNT(DISTINCT)
浮现在脑海中),但一般来说,数据移动比简单聚合函数更昂贵。
您没有提及数据库,但许多人允许:
HAVING Total > 100
或者使用子查询/ CTE通常对性能没有影响。