4

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

  • 具有 PK id 的表所有者
  • 带有 PK id 和 FK owner_id 的表 Parent 指的是 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 万个子行和 1000 个父行)级联的所有者行时,工作速度非常快(几秒钟),但有时需要将近一个小时。

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

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

我正在使用 Postgres 9.1.6

4

1 回答 1

0

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

您最初应该看的几件事是您是否可以找到任何模式。看看SELECT * FROM pg_locks它什么时候发生。当问题发生时,您还应该SELECT * FROM pg_stat_activity查看可能持有锁的位置。

于 2013-04-18T10:49:01.243 回答