【发布时间】:2012-11-30 02:25:03
【问题描述】:
我在表之间有一些关系,这些关系都与一个“所有者”表相关。所以只是为了这个例子:
- 具有 PK id 的表所有者
- 带有 PK id 和 FK owner_id 的表父级引用 Owner.id,上面有索引,以及
ON DELETE CASCADE。 - 具有 PK id 和 FK parent_id 的 Table Child 引用 Parent.id,上面有一个索引,以及
ON DELETE CASCADE。
Child 表很大(约 5000 万行),Parent 表有几千行,而 Owner 表非常小(约 10 行)。
还有一些与 Owner 和 Parent 相关的其他表,但它们相对较小(几千个)并且还具有外键索引和 ON CASCADE DELETE。
有时,当我删除通过所有删除级联的所有者行(大约 1200 万个子行和 1000 个父行)时,工作速度非常快(几秒钟),但有时需要将近一个小时。
我如何找出造成这种情况的原因?我在delete from child where parent_id in (select id from parent where owner_id = 1) 上做了explain,其中 1 是所有者行之一的 id(我尝试了各种 id 只是为了确保),据说它正在使用 Bitmap Heap Scan -> Bitmap Index Scan and Index Scan .但是,我不确定我是否在模仿ON DELETE CASCADE 触发器时的实际操作。我怎样才能弄清楚是什么导致了这些巨大的延误?是不是有时 Postgres 更喜欢进行顺序扫描(由于行数)?
插入相同的行只需要 8 分钟(包括应用程序逻辑和几千个事务提交),所以我不明白为什么直接删除需要这么长时间。
我正在使用 Postgres 9.1.6
【问题讨论】:
-
请尝试解释分析
-
尝试解释从 child where parent_id in (select_id from parent where owner_id = 1) 中删除分析并获得相同的位图堆扫描 -> 位图索引等。得到这些成本:(成本 = 150.01.. 562757.84 rows=6560827 width=12) (实际时间=39.792..39.792 rows=0 loops=1)
-
有可怕的错误统计 - 所以位图索引扫描不是最佳的 - 请尝试禁用 bitmap_scan -- "set enable_bitmapscan to off"
-
我执行了
set enable_bitmapscan to off并再次执行了explain analyse,现在它只使用了index scan。但是我再次尝试删除它仍然需要很长时间:( -
@Matthieu 不幸的是没有。现在已经有几年了,但如果我记得清楚的话,当我需要删除如此大量由外键链接的子项时,我删除了索引并在之后重建了它们。