如何在函数中更新EXECUTE格式块的结果(PostgreSQL)

时间:2016-07-31 09:27:57

标签: postgresql function

下面是检查PostgreSQL数据库中所有表的实际计数的一个很好的函数。我找到了here

从我的本地测试来看,似乎该函数仅在完成所有100个表的计数后才返回所有结果。

我想让它更实用。如果我们可以在完成表格后立即保存每个表的结果,那么我们可以检查所有计数作业的进度,而不是等待结束。

我想如果我能在完成第一张表后立即更新此功能的结果,那么这对我的要求是很好的。

在此函数完成第一个表的计数后,您能告诉我如何将结果更新到表中吗?

{{1}}

更新

我决定使用shell脚本来运行下面的函数作为后台进程。该函数将生成一个处理日志文件,以便我可以检查当前进程。

1 个答案:

答案 0 :(得分:1)

我认为你的想法很好,但我也认为它不会在PostgreSQL上“开箱即用”。我不是这方面的专家,但是MVCC在PostgreSQL上的工作方式,它基本上可以做所有DML,最好被理解为临时空间,然后当一切按预期工作时,它会全部移动最后。

这有很多优点,最值得注意的是,当有人更新表时,它不会阻止其他人查询那些相同的表。

如果这是Oracle,我认为您可以使用commit,在存储过程中完成此操作,但这不是Oracle。而且公平地说,Oracle不允许截断在PostgreSQL的方式中在存储过程中回滚,因此有给予和接受。

同样,我不是专家,所以如果我搞砸了一两个细节,请随时纠正我。

所以,回到解决方案。 COULD 实现此目的的一种方法是将服务器设置为远程服务器。像这样的东西会起作用:

CREATE SERVER pgprod
FOREIGN DATA WRAPPER dblink_fdw
OPTIONS (dbname 'postgres', host 'localhost', port '5432');

假设您有一个存储表和计数的表:

create table table_counts (
   table_name text not null,
   record_count bigint,
   constraint table_counts_pk primary key (table_name)
);

如果您不希望看到这些结果发生,那么这样的结果就可以用于单个模式。制作所有模式很容易,所以这只是为了说明:

CREATE or replace FUNCTION rowcount_all(schema_name text)
  returns void as
$$
declare
 rowcount integer;
 tablename text;
begin
  for tablename in SELECT c.relname FROM pg_class c
    JOIN pg_namespace s ON (c.relnamespace=s.oid)
    WHERE c.relkind = 'r' AND s.nspname=schema_name
    ORDER BY c.relname
  LOOP
    EXECUTE 'select count(*) from ' || schema_name || '.' || tablename into rowcount;
    insert into table_counts values (schema_name || '.' || tablename, rowcount)
    on conflict (table_name) do 
    update set record_count = rowcount;
  END LOOP;
end
$$ language plpgsql;

(这个预设为9.5或更高 - 如果没有,请自己手动卷起)。

但是,由于您希望对表进行实时更新,因此可以将相同的upsert放入dblink表达式中:

    perform dblink_exec('pgprod', '
         << your upsert statement here >>
    ');

当然,DBlink中SQL的格式化现在有点棘手,但是一旦你掌握了它,你可以在后台运行该函数并在运行时查询表以查看动态结果。

我认为这与实时获取信息的必要性有关。