【问题标题】:How to report progress from long-running PostgreSQL function to client如何从长时间运行的 PostgreSQL 函数向客户端报告进度
【发布时间】:2012-08-11 16:34:25
【问题描述】:

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

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

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

【问题讨论】:

    标签: .net sql postgresql plpgsql npgsql


    【解决方案1】:

    没有什么比发出通知更好的了。

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

    【讨论】:

    • 使用 PostgreSQL 8.4 及更高版本,您还可以向 RAISE NOTICE 提供错误代码,这样可以更轻松地区分进度消息和可能发出的其他通知。
    • 你是对的,事实证明 NOTICEs 正在在它们被提升时被传递,但是函数中出现了一个非常奇怪的减速,这并没有发生当我直接运行相同的查询时。我现在已经找到了解决方法。
    • RAISE NOTICE 有相对显着的开销——它是客户端和服务器之间的网络握手。我通常不会每次迭代都引起注意,但我会注意到每千次迭代。
    • 我为长时间转换 SQL 函数写了函数计数器 - 也许它对你有用okbob.blogspot.cz/2010/11/…
    【解决方案2】:

    除了@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

    不用说这不是可移植的,并且不能保证序列中的SELECTing 将始终以这种方式工作。不过,它非常方便。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 谢谢,但在这种特殊情况下,这并不简单,我可以向你保证。 :) 还有其他方法吗?
      • 我想不到,抱歉
      【解决方案4】:

      你也可以使用:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-04-29
        • 2014-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-14
        • 1970-01-01
        相关资源
        最近更新 更多