【问题标题】:How to optimize the performance of a stored procedure in Postgres?如何优化 Postgres 中存储过程的性能?
【发布时间】:2019-08-03 22:01:52
【问题描述】:

我在 Ubuntu 18.04.1 上使用 PostgreSQL 10.9。以下存储过程确实将数组作为输入和变量 beta。两个输入变量都用于计算聚合索引。数组可以有不同的长度。 由于我在另一个查询中使用了数千次此函数,因此此函数的性能非常重要。我删除了一个 CTE 并将其更改为子查询,这有点帮助。但是我找不到任何其他方法来进一步提高性能。

CREATE OR REPLACE FUNCTION public.part_accessibility_index(traveltime_array NUMERIC[], beta numeric)
RETURNS SETOF NUMERIC 

LANGUAGE sql
AS $function$

    SELECT COALESCE(sum_index,0) 
    FROM 
    (
        SELECT sum(part) sum_index
        FROM ( 
            SELECT EXP(UNNEST(traveltime_array)*(beta)) AS part
        )
        index_part 
    )
    sum_index;

$function$

函数可以这样调用

SELECT part_accessibility_index(ARRAY[100.2,323.9,1323.313,432.232,1100.22,144.1], -0.001)

我得到以下查询计划。

ProjectSet  (cost=0.00..5.27 rows=1000 width=32) (actual time=0.180..0.184 rows=1 loops=1)
  ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.001 rows=1 loops=1)
Planning time: 0.022 ms
Execution time: 0.197 ms

如前所述,查询并不是很慢,但可能仍有改进方法。我很乐意为您提供任何帮助!

【问题讨论】:

    标签: sql postgresql performance stored-procedures


    【解决方案1】:

    您可以尝试一些可能有助于提高性能的方法:

    1. 用 C 重写函数。这显然是最大的努力,但如果您真的需要性能,这可能是最大的回报。
    2. 您可以通过将合并向下移动到coalesce(sum(part), 0) 来删除一个子查询。事实上,我认为您不需要任何子查询:
      SELECT coalesce(sum(exp(part*beta)), 0) sum_index
            FROM UNNEST(traveltime_array) AS u(part)
    
    1. 您的函数没有返回集合。将其更改为仅返回数字。
    2. 尝试将其更改为 plpgsql 函数。如果计划不明显差于通用计划,则查询计划可能会在每个会话第五次执行后被缓存。
    3. 由于该函数不修改数据库或使用会话信息,因此可以安全地将其标记为不可变,这可能有助于优化器选择更好的计划。
    4. 同样,该函数可以标记为并行安全,这将允许并行工作人员调用该函数。如果可以并行化调用查询,这可能会有所帮助。

    【讨论】:

      【解决方案2】:

      谢谢杰里米!我遵循了你的大部分建议。除了重写函数;)

      CREATE OR REPLACE FUNCTION public.part_accessibility_index(traveltime_array NUMERIC[], beta numeric)
      RETURNS NUMERIC 
      AS $function$
      DECLARE 
          sum_index NUMERIC;
      BEGIN 
          SELECT COALESCE(sum(part),0) INTO sum_index
          FROM ( 
              SELECT EXP(UNNEST(traveltime_array)*(beta)) AS part
          )
          index_part; 
          RETURN sum_index; 
      END;
      $function$ LANGUAGE plpgsql immutable;
      

      特别是添加关键字 immutable 使得执行时间更快。尽管现在计划时间明显更长。我找不到任何解决方案。

      Result  (cost=0.00..0.01 rows=1 width=32) (actual time=0.000..0.000 rows=1 loops=1)
      Planning time: 0.126 ms
      Execution time: 0.004 ms
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-20
        • 2015-06-26
        • 2010-10-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多