PostgreSQL子查询/CTE是否被缓存?

3

“Cached”指的是在每次获取行时是否会对子查询进行调用?

以下是几个示例:

-- Simple query
SELECT * FROM (
    SELECT * FROM accounts
) AS subquery;

-- Subquery with function
SELECT * FROM (
    SELECT AVG(id_groups) FROM accounts
) AS subquery;

-- More messy queries
SELECT * FROM (
  SELECT id_groups, AVG(id_accounts) OVER (PARTITION BY id_groups)
  FROM accounts
) AS subquery
GROUP BY subquery.id_groups, subquery.avg;

此外,

两者有何不同?

SELECT * FROM (
    SELECT * FROM accounts
) AS subquery;

并且

WITH everything_about_accounts AS (
    SELECT * FROM accounts
)
SELECT * FROM everything_about_accounts;

使用视图而不是子查询工作方式是否相同,除了中间表之外,视图有一个名称?我在这里询问的是普通视图,而不是物化视图,因为物化视图只是可以轻松刷新的表。 - Bartłomiej Sobieszek
1
@TimBiegeleisen:在Postgres中,CTE不会被内联处理:例如,请参见此处https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/。 - user330315
@a_horse_with_no_name,我不知道这一点,谢谢您的评论。我猜SQL Server和Postgres在这方面非常不同。 - Tim Biegeleisen
1
@TimBiegeleisen:这是Postgres开发人员在实现时做出的有意识的设计决策。关于它是否是一个好的决策的讨论仍在继续 ;) - user330315
1个回答

4
关于FROM子句中的子查询:
在返回每一行时执行子查询是没有意义的,因此子查询不会被执行。
在您提出的三种情况中,PostgreSQL甚至会展开子查询:优化器意识到子查询是不必要的,并相应地转换查询。
使用您的查询和EXPLAIN来查看它的运作方式。
关于CTE:
与FROM子句中的子查询不同,CTE充当一个优化障碍,即优化器不会尝试将其展开或将条件推入其中。
相反,CTE被执行并且结果被实现,查询在实现结果上执行CTE扫描。
同样,使用EXPLAIN来查看它的运作方式。
PostgreSQL社区正在努力消除CTE始终被实现的限制(或特性,因为这是指导优化器的一种方式)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接