【问题标题】:Postgres 12: why does stored procedure start slowing after running many timesPostgres 12:为什么存储过程在运行多次后开始变慢
【发布时间】:2020-09-29 08:05:36
【问题描述】:

我在 Postgres 12 上重复运行存储过程,每次运行不同的日期。最初,存储过程需要 3 到 10 秒才能运行,但在连续运行多次后,大约一个小时,存储过程开始需要更长的时间(大约 1 分钟或更长时间)。

存储过程中使用的表的简单查询也开始需要比平时更长的时间来运行。在此表上运行 VACCUUM ANALYZE 后,查询再次加速。

我想知道导致查询开始运行如此缓慢的问题可能出在哪里。

我已经对来自部分存储过程的简单查询运行了解释(分析,缓冲区)并将其保存在以下链接中,也很高兴分享完整存储过程的解释(分析,缓冲区)。

在存储过程快速时解释(Analyse, Buffer):https://explain.depesz.com/s/yrse

在存储过程慢时解释(Analyse, Buffer):https://explain.depesz.com/s/uQel

产生解释(分析,缓冲区)的代码

SELECT period_id, classification_id,dtz,now() as create_dt,now() as update_dt,
                       false as latest_record,ratio_1
    FROM zpart.ratios_y2020 r
    where  classification_id is not null and universe_weight is not null
      and dtz='2020-03-28 00:00'::timestamptz

以下是特定日期的存储过程代码。

create temp table t_rr as
with cte as (
    SELECT period_id, classification_id,dtz,now() as create_dt
             ,now() as update_dt,false as latest_record,ratio_1
    FROM zpart.ratios_y2020 r
    where  classification_id is not null and universe_weight is not null
      and dtz='2020-03-28 00:00'::timestamptz
)
SELECT period_id, classification_id,dtz,now() as create_dt,now() as update_dt,false as latest_record
     , percentile_cont(array(SELECT generate_series(0, 99) :: NUMERIC / 100)) WITHIN GROUP
                                 (ORDER BY ratio_1) AS lower_bounds_1
FROM cte r
GROUP BY period_id, classification_id, dtz
union all
SELECT period_id, 1 as classification_id,dtz,now(),now(),false
     ,percentile_cont(array(SELECT generate_series(0, 99) :: NUMERIC / 100)) WITHIN GROUP
                                 (ORDER BY ratio_1) AS lower_bounds_1
FROM cte r
GROUP BY period_id, dtz
union all
SELECT  period_id, 2 as classification_id,dtz,now(),now(),false
     ,percentile_cont(array(SELECT generate_series(0, 99) :: NUMERIC / 100)) WITHIN GROUP
                                (ORDER BY ratio_1) AS lower_bounds_1
FROM cte r
where  classification_id!=3
GROUP BY period_id, dtz;

insert into zpart.rank_ranges_y2020(period_id, classification_id, dtz, create_dt, update_dt,
latest_record, lower_bounds_1)
SELECT period_id, classification_id, dtz, create_dt, update_dt, latest_record,lower_bounds_1
FROM t_rr r
on conflict (dtz,period_id,classification_id) do update set update_dt=now(),
latest_record=EXCLUDED.latest_record,lower_bounds_1=EXCLUDED.lower_bounds_1;
truncate t_rr; drop table if exists t_rr;

编辑 问题是由 ReadIOP 超出其分配引起的,随着时间的推移导致数据库变慢。

【问题讨论】:

  • 索引的定义是什么?
  • 请为这些查询显示EXPLAIN (ANALYZE, BUFFERS),最好在打开track_io_timing之后显示
  • 我更新了帖子中的链接以显示EXPLAIN (ANALYZE, BUFFERS) 的输出。表上的索引在 (security_id, period_id, dtz) 上定义为唯一的。该表还按 period_id 分区,这就是为什么您会在解释分析中看到诸如 ratiosy2020p9 之类的表名。有 7 个不同的 period_id(1、9、11、12、14、15、17)。
  • 您是否让交易保持打开状态?

标签: postgresql stored-procedures


【解决方案1】:

对于这个查询,您没有一个很好的索引。您需要一个第一列为dtz 的索引。您现有的索引被完全读取以找到它需要的行,换句话说,它没有被用作传统索引,而只是用作“瘦”表。

我不知道为什么查询从快到慢。差异显然在于 IO 时序,但尚不清楚是什么原因造成的。可能只是您系统中的其他活动开始要求自己的 IO,而竞争减慢了您正在查看的查询的 IO。或者可能是其他活动迫使您需要的数据从文件系统缓存中取出。但无论如何,一个更好的索引应该会变得无关紧要。

【讨论】:

  • 感谢您的回复,我更改了桌子上的索引,但并没有太大的区别。我联系了 AWS,问题是读取 IOP 受到限制,因为它超出了数据库的分配 IOP,最终导致查询变慢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多