存储过程的PSQL替换太慢

存储过程的PSQL替换太慢,sql,postgresql,stored-procedures,sqlperformance,postgresql-performance,Sql,Postgresql,Stored Procedures,Sqlperformance,Postgresql Performance,我有物业,每个物业都有合同,每个合同都有整型字段租赁面积 以前,我必须获得所有合同的租赁面积,按财产进行汇总,这是有效的 SELECT Sum(cr.rental_area) total_property_rental_area, -- bunch of other cr fields FROM appdata.contract_rental cr INNER JOIN appdata.domain_building b1

我有
物业
,每个
物业
都有
合同
,每个
合同
都有整型字段
租赁面积

以前,我必须获得所有合同的
租赁面积
,按财产进行汇总,这是有效的

 SELECT 
        Sum(cr.rental_area)         total_property_rental_area,
        -- bunch of other cr fields
 FROM  appdata.contract_rental cr
        INNER JOIN appdata.domain_building b1 
                ON ( b1.building_id = cr.building_id ) 
        INNER JOIN appdata.domain_immovable im1 
                ON ( im1.immovable_id = b1.immovable_id ) 
 GROUP  BY im1.property_id
现在,逻辑改变了,合同中有一个
期间的列表
,其中一个期间包含该合同的
租赁区
。找到正确的
周期
需要一些特殊的逻辑

我试图将逻辑连接到查询,但找不到放置它的位置,因此我必须创建存储过程

SELECT Sum(p.rental_area) total_property_rental_area 
       -- bunch of other cr fields
FROM   appdata.contract_rental cr 
       JOIN appdata.rental_period p 
         ON p.id = Get_current_period_id(cr.contract_rental_id, 
                   cr.end_date_actual) 
       INNER JOIN appdata.domain_building b1 
               ON ( b1.building_id = cr.building_id ) 
       INNER JOIN appdata.domain_immovable im1 
               ON ( im1.immovable_id = b1.immovable_id ) 
GROUP  BY im1.property_id   
程序:

CREATE OR REPLACE FUNCTION appdata.get_current_period_id(in contract_id_in bigint, in end_date_actual_in Date)
  RETURNS bigint AS
$BODY$
DECLARE
    period_id bigint;
BEGIN
    -- find the period that matches with end date or current date
    select id into period_id
       from rental_period
       where contract_id = contract_id_in
         and Coalesce(end_date_actual_in, Now()) >= start_date
       order by start_date desc  limit 1;
    -- if there was no period, just take the first one
    IF period_id is null THEN
        select id into period_id
           from rental_period
           where contract_id = contract_id_in
           order by start_date asc
           limit 1;
    END IF;

    return period_id;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

但是现在它太慢了,有没有一种方法可以将周期查找逻辑放入sql中以使其更快,而不使用存储过程要点是,对于reach契约,它只需要根据逻辑获取单个句点。

将存储过程回滚到主SQL中,主要提示是合并两个查询(如果一个为null,则使用另一个)

例:代替

p.id = Get_current_period_id(cr.contract_rental_id, 
               cr.end_date_actual)
使用:

根据以下评论,以下索引也可能有所帮助:

 create index on rental_period (contract_id, start_date asc) 

请务必在事后分析该表以更新统计数据。

哇,它可以工作,但我不明白如何工作?它基本上是相同的查询,但速度要快得多?存储过程就是所谓的优化“墙”。内部优化器尝试将流程作为一个整体进行检查,以找出获得结果的最佳方式。当放在一个sql语句中时,优化器会有更多的信息,并更好地理解它在做什么。一旦它撞到墙上,它就不能再优化了。。。因此,它可以独立地优化过程和SQL语句。将它们放在一起通常会神奇地产生更好的性能。那些order by和limit 1也可能被优化掉,如果按“where”字段中的所有列编制索引,并且具有正确的asc/desc顺序,它们的性能也会更好。如果您对结果感到满意,您可以停止尝试优化它。如果您想让它看起来更好一点,可以使用“with”语句将查询分成更容易理解的部分。(查找CTE或通用表表达式)脱离主题:通过使开始日期和结束日期不可为空,并将默认值设置为
-infinity
+infinity
@joop,可以避免
合并(end\u date\u actual\u in,Now())
构造,但是接下来我必须检查值是-infinity还是+infinity而不是null,所以我认为性能方面是一样的。同样在UI中,它们将始终作为一些值进行赋值,并尝试在那里显示它们,而不是显示空字段。
 create index on rental_period (contract_id, start_date asc)