根据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;
答案 0 :(得分:0)
我认为答案是否定的,对STABLE函数的多次调用在整个CTE中没有得到优化。我不知道如何证明它,但是根据PostgreSQL: Documentation: 11: 7.8. WITH Queries (Common Table Expressions),CTE似乎是单独的“辅助声明”。而且,它们似乎没有与父查询很好地集成在一起。例如:
。 。 。与普通子查询相比,优化器无法将限制从父查询向下推到WITH查询。通常,WITH查询将被评估为已写入,而不会抑制父查询之后可能会丢弃的行。