如何从频繁访问的表中删除许多行

时间:2016-02-03 22:22:05

标签: postgresql indexing transactions locking postgresql-performance

我需要删除一个非常大的表(例如,5米行)的大多数(比方说,90%)。该表的另外10%经常被读取,但不会被写入。

从“Best way to delete millions of rows by ID”,我收集到我应该删除90%我删除的任何索引,以加快进程(除了我用来选择要删除的行的索引)。

从“PostgreSQL locking mode”,我看到此操作将在整个表上获得DELETE FROM table WHERE delete_flag='t'锁定。但由于我只是其他10%,这应该没关系。

那么,在一个命令中删除所有内容是否安全(即{{1}})?我担心如果删除一行失败,触发巨大的回滚,那么它将影响我从表中读取的能力。批量删除会更明智吗?

1 个答案:

答案 0 :(得分:4)

  1. 索引对90%的所有行的操作完全没用。无论哪种方式,顺序扫描都会更快。

  2. 如果需要允许并发读取,则不能对表进行独占锁定。因此,您也不能删除同一事务中的任何索引。

  3. 可以删除单独事务中的索引,以使独占锁的持续时间保持最短。 然后使用CREATE INDEX CONCURRENTLY在后​​台重建索引 - 只需要一个非常简短的独占锁。

  4. 如果您有一个稳定的条件来确定剩余的10%的行,我强烈建议只为这些行partial index以获得最佳效果:

    • 阅读查询可以随时快速访问表格(使用部分索引)。
    • DELETE根本不会修改部分索引,因为DELETE中没有涉及任何行。

    CREATE INDEX foo (some_id) WHERE delete_flag = FALSE;
    

    假设delete_flagboolean。您必须在查询中包含相同的谓词(即使它看起来在逻辑上是多余的),以确保Postgres能够理解它可以使用部分索引。