为什么ON DELETE CASCADE有时需要花费很长时间才能使用Postgres 9?

时间:2012-12-12 11:32:04

标签: postgresql postgresql-9.1

我在表之间有一些关系,这些关系都与一个'所有者'表相关。所以只是为了这个例子:

  • 具有PK id的表所有者
  • 表父PK ID和FK owner_id引用Owner.id,上面有索引,ON DELETE CASCADE
  • 具有PK id和FK parent_id的表Child,引用Parent.id,并带有索引,ON DELETE CASCADE

Child表很大(约5000万行),Parent表有几千行,Owner表非常小(~10行)。

还有一些与Owner和Parent相关的其他表,但它们相对较小(几千),并且还有外键索引和ON CASCADE DELETE

有时当我删除所有删除的行所有者行(大约1200万个子行和1千个父行)时,工作速度非常快(几秒钟),但有时需要将近一个小时。

我如何找出造成这种情况的原因?我在explain上做了delete from child where parent_id in (select id from parent where owner_id = 1),其中1是所有者行之一的ID(我尝试了各种ID以确保)并且它说它正在使用位图堆扫描 - >位图索引扫描和索引扫描。但是我不确定我是否在模仿ON DELETE CASCADE触发器时实际完成的操作。我怎样才能弄清楚造成这些巨大延误的原因?可能有时Postgres更喜欢进行顺序扫描(由于行数)?

插入相同的行只需要8分钟(包括应用程序逻辑和几千个事务提交),所以我无法弄清楚为什么直接删除需要这么长时间。

我正在使用Postgres 9.1.6

1 个答案:

答案 0 :(得分:0)

你说有时它会从几秒钟到几小时。要删除的行数相当多。您可能正在处理从数据缓存到行锁的各种因素。不幸的是,如果这些是瞬态条件,那么当它没有发生时可能很难跟踪它们。

您最初应该注意的一些事项是,您是否可以在发生这种情况时找到任何模式,以及SELECT * FROM pg_lock何时发生。发生问题时,您还应SELECT * FROM pg_stat_activity查看锁定的位置。