该功能在循环之前被卡住。
RewriteCond %{HTTP_HOST} !^(www|sub)\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}/$1 [R=301,L,NE]
打印消息“开始...”,但不会打印消息“...结束”。
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)
现在我找到了解决方案。但我想知道它是怎么发生的!
答案 0 :(得分:1)
如果通过对查询进行如此肤浅的更改来修复它,那么它可能不会被卡住"但由于选择不当的执行计划而只是非常缓慢地运行。
查询在函数中的性能比它本身更差的事实可能是plan caching的结果。基本上,Postgres可能会尝试通过创建和重用通用(即参数独立)执行计划来避免重新规划查询的成本。不幸的是,这些通用计划可能远非最佳。
糟糕计划的可能解释是糟糕的统计数据;如果Postgres没有关于数据的准确信息,它必然会做出糟糕的决定。所涉及的ANALYSE
表可能有所帮助,但通常不需要这样做 - autovacuum通常应该使统计数据保持最新(假设你已经运行)。
统计偏差的一个常见原因是值的分布不均匀(在您的情况下,如果每个连接的数据包数量有很大差异)。通过使用ALTER TABLE ... SET STATISTICS
(后跟ANALYSE
)提高统计信息的详细程度,可以大大改善这一点。在某些情况下,高值会减慢计划,但500(可能)是一个安全的起点。
如果没有其他方法可行,您可以通过EXECUTE
运行查询来绕过计划缓存。