简体   繁体   English

Postgres如何在内部实现删除级联?

[英]How does Postgres implement a delete cascade internally?

I've implemented a manual delete cascade in Postgres recently. 我最近在Postgres中实现了手动删除级联。 I used pg_depend and DFS over this table to get the hierarchy from the objects, but it is not as fast as Postgres' own implementation. 我在此表上使用了pg_depend和DFS来从对象中获取层次结构,但是它不如Postgres自己的实现快。 So how does Postgres implement this internally? 那么Postgres如何在内部实现呢?

PostgreSQL's implementation of update/delete cascade is very simple. PostgreSQL的更新/删除级联的实现非常简单。 It's basically a for each row ... on delete ... execute procedure ... trigger that reaches out and does a delete from only [othertable] where [foreign_key_col] = OLD.[primary_key_col] . 基本上for each row ... on delete ... execute procedure ...都是一个for each row ... on delete ... execute procedure ...触发器, delete from only [othertable] where [foreign_key_col] = OLD.[primary_key_col]进行delete from only [othertable] where [foreign_key_col] = OLD.[primary_key_col] It has a few tricks that aren't available to user-level triggers, but that's the gist of it. 它具有一些用户级触发器不可用的技巧,但这就是要点。

See RI_FKey_cascade_del in src/backend/utils/adt/ri_triggers.c for details. 有关详细RI_FKey_cascade_del ,请参见src/backend/utils/adt/ri_triggers.c

Performance is OK when there's an index on the foreign (referencing) side of a FK relationship, and truly awful when the referencing side is a large table with no index on the referencing column. 当FK关系的外部(引用)侧有索引时,性能正常;如果引用侧是在索引列中没有索引的大型表,则性能真差劲。

PostgreSQL (or at least 9.6 and oler) is not smart enough to batch up keys to delete and do a single big DELETE FROM . PostgreSQL(或至少9.6和oler)不够智能,无法批量添加要删除的密钥并执行一个大的DELETE FROM It can't accumulate the pending-deletion keys in a tuplestore. 它无法在元组存储中累积挂起删除键。 It has to dispatch each delete immediately, or (if the FK relationship is deferred) accumulate it in a queue of triggers to fire, which are still fired individually. 它必须立即调度每个删除操作,或者(如果推迟了FK关系)将其累积在触发触发器的队列中,这些触发器仍然单独触发。

You should be able to easily beat the performance of a cascade delete by using DELETE ... FROM ... USING ... or a DELETE ... WHERE EXISTS (...) to batch delete rows you will then delete from the parent table. 通过使用DELETE ... FROM ... USING ...DELETE ... WHERE EXISTS (...)批量删除行,然后将其从中删除,您应该能够轻松胜过级联删除的性能。父表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM