Function 将PL/pgSQL函数分解为更小的部分

Function 将PL/pgSQL函数分解为更小的部分,function,postgresql,plpgsql,Function,Postgresql,Plpgsql,我想写一个模块化的API函数。问题是,模块化零件的功能 同样的疑问。我怀疑,每个子函数中的相同查询都会影响性能 例如: MAIN_FUNCTION: base_data(customer_id, user_id) { SELECT * FROM get_absence(customer_id, user_id) JOIN get_work_hours(customer_id, user_id) USING (worker_id)

我想写一个模块化的API函数。问题是,模块化零件的功能 同样的疑问。我怀疑,每个子函数中的相同查询都会影响性能

例如:

    MAIN_FUNCTION: base_data(customer_id, user_id) {
      SELECT *
        FROM get_absence(customer_id, user_id)
        JOIN get_work_hours(customer_id, user_id)
       USING (worker_id)
    }

    get_absence(customer_id, user_id) {
      RETURN QUERY
      SELECT *
        FROM get_user_workers(customer_id, user_id)
        JOIN absence_table
       USING (worker_id)
    }

    get_work_hours(customer_id, user_id) {
      RETURN QUERY
      SELECT *
        FROM get_user_workers(customer_id, user_id)
        JOIN workhours_table
       USING (worker_id)
    }
对不起,伪代码比较短。基本上,大多数子函数都包含get\u user\u workers查询。如果我要构建一个大而乏味的函数,我会用公共表表达式查询worker

如何实现可读性和模块化,而不是无数行的查询?

您可以轻松做到这一点:

CREATE FUNCTION get_absence(...)  RETURNS TABLE (...) ...;
CREATE FUNCTION get_work_hours(...) RETURNS TABLE (...) ...;

CREATE FUNCTION base_data(_customer_id int, _user_id int)
  RETURNS TABLE (...) AS
$func$
   SELECT a.*, w.*
   FROM   get_absence(_customer_id, _user_id) a
   JOIN   get_work_hours(_customer_id, _user_id) w ON w.??? = a.???;
$func$ LANGUAGE sql;
在简单示例中使用SQL函数。PL/pgSQL也是如此,因为问题实际上是SQL的问题

FROM
子句中,可以像使用表一样使用set返回函数。但调用集返回函数具有:

SELECT * FROM base_data(1,2);
从基本数据(1,2)中选择*
请注意,简单的SQL函数可以“内联”,而PL/pgSQL函数总是单独执行(充当优化屏障)——但它们的执行计划会在同一个会话中保存和重用(如果Postgres发现这样更便宜的话)。各有利弊

通常,没有子函数的单个集成优化查询是最快的。根据许多情况,可能很难起作用或产生相关的影响

详情:


始终包含完整的函数页眉(和页脚),其中包含名称、参数、数据类型、返回类型、语言声明等。。。当然,你的博士后版本。你的最后一句话真的是你的问题吗?在文章的其余部分,你似乎真的在问:“如何避免多次调用get_user_workers()”?从性能角度来看,这种风格最糟糕。您可以非常有效地阻止查询优化器。SQL不支持这种小粒度。如果需要,可以使用一个视图,而不是简单的单行sql查询函数。我认为没有必要添加完整的页眉和页脚,因为问题不在于小的调整,而在于一般的方法。不,问题不仅在于如何避免调用functionX N次,还在于如何获得优雅且可维护的代码。我认为这只是一种错误的策略——这应该通过视图而不是函数来实现。您尝试合并功能世界和关系世界。它应该适用于较小的项目,其中查询优化并不重要,但对于大型数据库来说,这种策略完全是错误的——一个函数API必须包装一个完整的优化查询。base_数据应该包含所有将要使用的函数,我不能在较低级别隐藏某些函数。谢谢Pavel,我将尝试使用视图之道。唯一让我感到困扰的是,我不能在视图中使用generate_系列。这意味着在主函数中有大量的SQL语句,部分被视图包围。似乎我可以在视图中使用会话变量。谢谢大家。@user1190411:这是一个误会。当然,您可以在函数中使用
generate_series()
。此外,一个简单的,
不可变的
sql函数(例如,只需选择1234
)就可以提供全局变量的等价物。你可以发布一个新的问题(简化的)全貌,以获得最佳解决方案。