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

Sim*_*kin 5 postgresql indexing locking transactions postgresql-performance

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

从" 按ID删除数百万行的最佳方式 ",我收集到我应该删除90%我删除的任何索引,以加快进程(除了我用来选择要删除的行的索引) .

从" PostgreSQL锁定模式 ",我看到这个操作将获取ROW EXCLUSIVE整个表的锁定.但是,因为我只是了另外的10%,这应该没有关系.

那么,在一个命令中删除所有内容是否安全(即DELETE FROM table WHERE delete_flag='t')?我担心如果删除一行失败,触发大量回滚,那么它将影响我从表中读取的能力.批量删除会更明智吗?

Erw*_*ter 7

  1. 索引通常对 90% 的行的操作无用。无论哪种方式,顺序扫描都会更快。(异国情调的例外适用。)

  2. 如果需要允许并发读取,则不能在表上使用排他锁。因此,您也不能删除同一事务中的任何索引。

  3. 可以在单独的事务中删除索引以将排他锁的持续时间保持在最短。在 Postgres 9.2 或更高版本中,您还可以使用DROP INDEX CONCURRENTLY,它只需要最少的锁。稍后用于CREATE INDEX CONCURRENTLY在后台重建索引 - 并且只需要一个非常简短的排他锁。

如果您有一个稳定的条件来识别保留的 10%(或更少)的行,我建议只对这些行进行部分索引,以获得最佳的两者:

  • 读取查询可以随时快速访问表(使用部分索引)。
  • bigDELETE根本不会修改部分索引,因为DELETE.
CREATE INDEX foo (some_id) WHERE delete_flag = FALSE;
Run Code Online (Sandbox Code Playgroud)

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