Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql Postgres中的多次删除,每次删除后都有一个提交_Postgresql_Sql Delete - Fatal编程技术网

Postgresql Postgres中的多次删除,每次删除后都有一个提交

Postgresql Postgres中的多次删除,每次删除后都有一个提交,postgresql,sql-delete,Postgresql,Sql Delete,我有大约3000万条记录要从表中删除,即使删除10.000条记录也需要30分钟。我关心的是对所有3000万条记录发出delete命令,所以我想批量删除 所以我的方法是循环删除一个批,然后提交,然后循环删除下一个批。但这会产生以下错误: LOCATION: exec_stmt_raise, pl_exec.c:3216 ERROR: 0A000: cannot begin/end transactions in PL/pgSQL HINT: Use a BEGIN block with an

我有大约3000万条记录要从表中删除,即使删除10.000条记录也需要30分钟。我关心的是对所有3000万条记录发出delete命令,所以我想批量删除

所以我的方法是循环删除一个批,然后提交,然后循环删除下一个批。但这会产生以下错误:

LOCATION:  exec_stmt_raise, pl_exec.c:3216
ERROR:  0A000: cannot begin/end transactions in PL/pgSQL
HINT:  Use a BEGIN block with an EXCEPTION clause instead.
这是我写的代码:

DO $$
BEGIN
    FOR i in 1..30000 loop
        DELETE FROM my_table
            WHERE id IN (
                SELECT id 
                    FROM my_table
                    WHERE should_delete = true
                    LIMIT 1000
            );
        RAISE NOTICE 'Done with batch %', i;
        COMMIT;
    END LOOP;
END
$$;

实现这一目标的替代方案是什么?

我突然想到了几件事:

  • PostgreSQL中的事务开销非常大。如果您在一个大型事务中完成这一切,您可能会看到性能的显著提高
  • 听起来好像您正在现场生产数据库上进行试验。不要那样做。使用统计上相似(或相同)的数据和相似的工作负载设置一个测试实例,并使用它。这样,如果您设法破坏了某些东西,那么只会损坏测试实例
  • 一旦通过(2)获得了一个测试实例,就可以使用它来测试(1)并查看它需要多长时间。那么你就不必猜测哪种方法更优越了
  • 您提到其他作业在固定时间运行。因此,这不是一个数据库支持(类似于)暴露于互联网的web服务器。它是一个批处理系统,在预定时间运行计划作业。由于您已经有一个计划系统,因此在系统未使用(或不太可能使用)时使用它来计划删除
  • 如果您决定必须使用多个事务,请使用PL/pgSQL以外的其他方法来执行实际的循环。例如,您可以使用shell脚本或其他编程语言,如Python或Java。任何带有Postgres绑定的东西都可以
  • 真正激进的方法是对整个数据库执行删除,对副本执行删除,然后用副本替换原始副本。交换可能需要将数据库短时间置于只读模式,以避免写入不一致,并允许副本聚合。因为您的系统是批处理系统,所以这可能无关紧要。显然,这是资源最密集的方法,因为它需要一个完整的额外数据库

  • 。。。这是由我的表的外键引起的…
    请添加表的定义,包括键和索引。如果要删除所有行,为什么不
    截断
    ?。。快速易用并不是所有的行,它就像60%的行扫描—禁用触发器或删除过程所需—添加一个支持FK:
    在my_child_表(父\u id)上创建索引的索引