如何报告从长时间运行的PostgreSQL函数到客户端的进度

时间:2012-08-15 11:15:33

标签: .net sql postgresql plpgsql npgsql

我有一个C#客户端应用程序,它使用Npgsql在PostgreSQL 9.1.4中调用plpgsql函数。该功能需要很长时间,我想以某种方式向客户报告进度。我该怎么做?

LISTEN / NOTIFY机制听起来很完美,除了整个事情在一个事务中运行,NOTIFY事件直到事务结束才发送,这对我来说是没用的。

我尝试过的另一件事是RAISE NOTICE,我可以在客户端上处理,但即使是那些通知似乎也会缓冲一段时间并分批发送。它总比没有好,但不理想。有什么方法可以“冲洗”它们,所以它们会立即发送给客户吗?

4 个答案:

答案 0 :(得分:7)

除了@ Pavel关于RAISE NOTICE的优点之外,还有另一种经典技术用于监控Pg中的查询进度。这有点像黑客,但它非常有效。

您可以利用这样一个事实,即序列的更改会立即在任何地方都可见,以便将函数的进度暴露给外部。使用硬编码序列并确保不同时调用该函数,或将进度监视序列名称传递给函数。

您的函数可以在每次迭代时调用nextval(seqname),并且感兴趣的各方可以使用来自另一个会话的SELECT last_value FROM seqname来检查序列的状态。

您可以通过

进行设置,使序列完成倒计时
create sequence test maxvalue 2147483647 increment by -1;

并在您的函数开头调用setval('seqname', num_items)。然后,每次nextval调用都会向下计数到零。顺便说一句,2147483647是maxint

毋庸置疑,这不是可移植的,并且无法保证序列中的SELECT始终以这种方式工作。但它很方便。

答案 1 :(得分:6)

没有比RAISE NOTICE更好的了。

这些信号没有被缓冲 - 它们是异步的 - 你的应用程序中的通知处理可能存在问题。

答案 2 :(得分:1)

最简单的方法是将pgsql函数拆分为多个子函数,而不是按顺序调用它们,应用程序端,管理应用程序中的事务范围。

答案 3 :(得分:0)

您也可以使用:

EXECUTE 'COPY (SELECT ''progress: ' || progress_variable || ''') TO ''d:\progress.txt''';

在函数内部,将当前进度写入文本文件。