如何禁用Postgresql中的所有约束?

时间:2019-05-28 05:24:51

标签: c# postgresql entity-framework-core

我有一个PostgreSQL数据库,其中的表具有超过5,000亿行。我正在尝试删除大约600万行,但这需要4分钟以上的时间。我需要优化那些删除操作,以创建有用的系统。

我认为一个好主意是禁用约束和触发器,然后重新启用它,所以我的问题是:

如何禁用所有约束? 而且,是否可以禁用表之间的关系?

现在,我只是使用以下方式禁用触发器:

Alter table "table_name" disable all

并使用以下命令重新启用它:

Alter table "table_name" enable all

编辑

这是启用了触发器的查询结果。

  Delete on "ParameterValues"  (cost=0.00..1015910.71 rows=47196359 width=6) (actual time=296995.938..296995.938 rows=0 loops=1)
  Buffers: shared hit=6000000 read=420811 dirtied=93346 written=51646
  ->  Seq Scan on "ParameterValues"  (cost=0.00..1015910.71 rows=47196359 width=6) (actual time=7977.126..19798.361 rows=6000000 loops=1)
        Filter: ("Id" < 23000000)
        Rows Removed by Filter: 34218414
        Buffers: shared read=420811 dirtied=49228 written=51646
Planning Time: 304.085 ms
Execution Time: 296995.963 ms

禁用所有触发器可以提高性能,将执行时间从5分钟减少到3分钟。

Alter table "table_name" disable trigger all

但是,我需要改进更多的删除操作。有想法吗?

2 个答案:

答案 0 :(得分:3)

禁用表上所有触发器的正确​​语句是

ALTER TABLE atable DISABLE TRIGGER ALL;

这将禁用表上定义的所有触发器和外键约束,因为外键约束是由PostgreSQL中的系统触发器实现的。

它还将禁用可延迟主键,唯一性和排除约束,这些约束也可以通过触发器实现。不可延迟的主键,唯一性和排除约束没有关联的触发器,也不会受到影响。

您以后可以通过启用触发器来重新启用这些约束,但是不会进行任何一致性检查。因为这样做很危险,所以禁用此类触发器需要超级用户特权。

禁用基于触发器的约束的另一种方法是将session_replication_role参数设置为replica,这也需要超级用户特权。

禁用检查约束和不可延迟的主键,唯一约束和排除约束的唯一方法是删除它们,然后重新创建它们。后者在检查表的一致性时会花费一些时间,但是您可能仍然会获胜,因为它将使数据修改更快。

有关参考,请参见ALTER TABLE的文档。

答案 1 :(得分:1)

如果您要使用纯pl / pgsql解决方案。您可以使用这样的匿名块(甚至可以使用以表名和模式作为参数的函数)。

final Aggregation aggregation = newAggregation(
        match(Criteria.where("key").is("KEYCODE001")),
        unwind("$values", true),
        unwind("$values.objects", true),
        match(Criteria.where("classId").is("CLASS_01")),
        project().and("$values.classId").as("classId").and("$values.objects").as("object"),
        group("classId", "objects").push("$object").as("objects").first("$classId").as("_id"),
        project().and("$_id").as("classId").and("$objects").as("objects")
);