我有一个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
但是,我需要改进更多的删除操作。有想法吗?
答案 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")
);