【问题标题】:Are multiple calls to a STABLE function optimized across CTEs?对 STABLE 函数的多次调用是否跨 CTE 进行了优化?
【发布时间】:2018-12-23 17:56:01
【问题描述】:

根据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;

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多