加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Postgresql函数卡在for循环中

发布时间:2020-12-13 15:52:51 所属栏目:百科 来源:网络整理
导读:该函数在循环之前被卡住. select * from scm_main.fn_connection_stations(1219646) 打印消息“开始…”但不打印消息“…结束”. CREATE OR REPLACE FUNCTION scm_main.fn_connection_stations(var_connection_id bigint)RETURNS SETOF scm_main.typ_connect
该函数在循环之前被卡住.

select * from scm_main.fn_connection_stations(1219646)

打印消息“开始…”但不打印消息“…结束”.

CREATE OR REPLACE FUNCTION     
scm_main.fn_connection_stations(var_connection_id bigint)
RETURNS SETOF scm_main.typ_connection_stations AS
$BODY$DECLARE 
    var_affected                 INTEGER DEFAULT 0; 
    var_row                      scm_main.typ_connection_stations%ROWTYPE; 
BEGIN 
    RAISE NOTICE 'Start...'; 
    FOR var_row IN 
    SELECT DISTINCT v.vbvdata_station_id
    FROM scm_main.tbl_vbvdata AS v 
    INNER JOIN scm_main.tbl_packet AS p ON (v.vbvdata_packet_id = 
    p.packet_id and p.packet_connection_id = var_connection_id) 
    --WHERE v.vbvdata_packet_id IN 
    --( SELECT packet_id FROM scm_main.tbl_packet AS o_p WHERE 
    o_p.packet_connection_id = var_connection_id) 
    LOOP 
        RETURN NEXT var_row; 
    END LOOP; 
    RAISE NOTICE '...End'; 
    RETURN; 
END 
$BODY$
  LANGUAGE plpgsql STABLE STRICT
  COST 100
  ROWS 1000;
ALTER FUNCTION scm_main.fn_connection_stations(bigint)
  OWNER TO postgres;

查询本身非常简单,并在直接调用时运行,如下所示:

SELECT DISTINCT v.vbvdata_station_id 
FROM scm_main.tbl_vbvdata AS v 
INNER JOIN scm_main.tbl_packet AS p ON (v.vbvdata_packet_id =  
p.packet_id and p.packet_connection_id = 1219646)

我想问题必须是桌子的锁定.但我绝对不明白是什么原因以及可以解决的问题.

前段时间评论部分正在运作.但过了一会儿,出现了同样的问题.我通过更改查询并用内部联接替换条件(级联查询)来解决它.但这次他们都没有工作!

更新

我通过一个愚蠢的改变再次使它工作:

INNER JOIN scm_main.tbl_packet AS p ON (v.vbvdata_packet_id = p.packet_id 
  and p.packet_connection_id = var_connection_id)`

改为:

INNER JOIN scm_main.tbl_packet AS p ON (v.vbvdata_packet_id = p.packet_id)
  where p.packet_connection_id in (select var_connection_id)

并且工作得很好.

另一个有趣的观点是,即使是下面的更改也无法正常工作并仍然挂起:

INNER JOIN scm_main.tbl_packet AS p ON (v.vbvdata_packet_id = p.packet_id) 
  where p.packet_connection_id = var_connection_id

现在我找到了解决方案.但我想知道它是怎么发生的!

解决方法

如果通过对查询的这种表面改变来修复它,那么它可能不会“卡住”,而是由于选择不当的执行计划而非常缓慢地运行.

查询在函数中的性能比它本身更糟的事实可能是plan caching的结果.基本上,Postgres可能会尝试通过创建和重用泛型(即参数独立)来避免重新规划查询的成本执行计划.不幸的是,这些通用计划可能远非最佳.

坏计划的一个可能解释是糟糕的统计数据;如果Postgres没有关于数据的准确信息,则必然会做出糟糕的决定.对所涉及的表进行分析可能有所帮助,但通常不需要这样做 – autovacuum通常应该使统计数据保持最新(假设您已运行).

统计偏差的一个常见原因是值的分布不均匀(在您的情况下,如果每个连接的数据包数量有很大差异).通过使用ALTER TABLE ... SET STATISTICS(后跟ANALYZE)提高统计信息的详细程度,可以大大改善这一点.在某些情况下,高值会减慢计划,但500(可能)是一个安全的起点.

如果没有其他工作,您可以通过EXECUTE运行查询来绕过计划缓存.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读