postgreSQL窗口函数:多次返回相同的avg()对性能的影响



我想从表a中选择一堆行,以及像avg(a .price)和avg(a .distance)这样的聚合函数的结果。

现在,SELECT查询花费了很多时间,所以我不想运行一个查询来获取行,而运行另一个查询来获取平均值。如果我这样做,我将运行查询来选择适当的行两次。

但是看看PostgreSQL窗口函数文档(http://www.postgresql.org/docs/9.1/static/tutorial-window.html),似乎使用窗口函数返回聚合函数的结果,我想在返回的行旁边使用意味着返回的每一行将包含聚合函数的结果。在我的例子中,由于聚合是针对主SELECT查询返回的所有行,而不是其行的子集,因此这似乎很浪费。

多次返回相同的avg()的性能影响是什么,假设我在a中选择了一个子集的行,但在整个子集上进行聚合查询?特别是,Postgres是每次重新计算平均值,还是以某种方式缓存平均值?

通过类比:如果您查看窗口函数文档,并假设depname对于SELECT查询返回的每一行都是'develop',并且每一行的平均值是相同的,因为平均值是在所有返回的行中计算的。这个平均值计算了多少次?

根据文档第7.2.4节:

当使用多个窗口函数时,所有在其窗口定义中具有语法等效的PARTITION BY和ORDER BY子句的窗口函数都保证在一次遍历数据中求值。

您可以使用CTE来做您想做的事情。根据Postgres文档:

WITH查询的一个有用的属性是它们只计算一次每次执行父查询,即使它们被多次引用父查询或同级WITH查询。因此,昂贵的在多个地方需要的计算可以放在一个WITH查询以避免冗余工作。另一个可能的应用是防止不必要的带有副作用的函数多次求值。然而,硬币的另一面是优化器更少能够将父查询中的限制下推到WITH查询中比普通子查询要好。通常会对WITH查询进行求值如前所述,不抑制父查询可能的行丢弃。(但是,如上所述,评估可能会停止早期如果对查询的引用需求只有有限的几个行。)

您可以使用如下结构来组织最终结果:

with cte as (your basic select goes here)
select *
from cte cross join
     (select averages here
      from cte
     ) const
where < your row filter here>

最新更新