跨CTE是否优化了对STABLE函数的多次调用?

时间:2018-12-23 17:56:01

标签: postgresql common-table-expression sql-function

根据PostgreSQL: Documentation: 38.7. Function Volatility Categories

  

STABLE函数无法修改数据库,并且在给定单个语句内所有行的给定相同参数的情况下,保证返回相同的结果。该类别使优化程序可以将函数的多个调用优化为单个调用。

使用CTE怎么办?如果我在CTE内部调用STABLE函数,然后在主SELECT查询中再次调用,优化器是否会将函数的两个调用优化为单个调用?

你怎么知道? (我不知道如何使用EXPLAIN。)

在下面不切实际的示例中,我想确保函数get_user_by_id()仅被调用一次。

CREATE TABLE users (
  id bigserial PRIMARY KEY,
  username varchar(64) NOT NULL
);

CREATE FUNCTION get_user_by_id(_id bigint) RETURNS users AS $$
  SELECT *
  FROM users
  WHERE id = _id
$$ LANGUAGE SQL STABLE;

INSERT INTO users (username) VALUES ('user1');

WITH error AS (
  SELECT -1 AS code
  WHERE (SELECT get_user_by_id(3) IS NULL)
)
SELECT code AS id, NULL AS username FROM error
UNION ALL
SELECT * FROM get_user_by_id(3) WHERE id IS NOT NULL;

1 个答案:

答案 0 :(得分:0)

我认为答案是否定的,对STABLE函数的多次调用在整个CTE中没有得到优化。我不知道如何证明它,但是根据PostgreSQL: Documentation: 11: 7.8. WITH Queries (Common Table Expressions),CTE似乎是单独的“辅助声明”。而且,它们似乎没有与父查询很好地集成在一起。例如:

  

。 。 。与普通子查询相比,优化器无法将限制从父查询向下推到WITH查询。通常,WITH查询将被评估为已写入,而不会抑制父查询之后可能会丢弃的行。