这一切都取决于...
假设没有对相关表的并发写访问,或者您可能必须以独占方式锁定表,或者这条路线可能根本不适合您。
删除所有索引(可能除了删除本身所需的索引)。
之后重新创建它们。这通常比对索引的增量更新快得多。
检查您是否有可以暂时安全删除/禁用的触发器。
外键是否引用您的表?它们可以被删除吗?暂时删除?
根据您的 autovacuum 设置,它可能有助于VACUUM ANALYZE
在操作之前运行。
根据您的设置,手册填充数据库的相关章节中列出的一些要点也可能有用。
如果您删除表的大部分并将其余部分放入 RAM,那么最快和最简单的方法可能是:
BEGIN; -- typically faster and safer wrapped in a single transaction
SET LOCAL temp_buffers = '1000MB'; -- enough to hold the temp table
CREATE TEMP TABLE tmp AS
SELECT t.*
FROM tbl t
LEFT JOIN del_list d USING (id)
WHERE d.id IS NULL; -- copy surviving rows into temporary table
-- ORDER BY ? -- optionally order favorably while being at it
TRUNCATE tbl; -- empty table - truncate is very fast for big tables
INSERT INTO tbl
TABLE tmp; -- insert back surviving rows.
COMMIT;
这样您就不必重新创建视图、外键或其他依赖对象。你会得到一张没有臃肿的原始(排序)表。
阅读temp_buffers
手册中的设置。只要表格适合内存,或者至少大部分适合内存,这种方法就很快。如果您的服务器在此操作过程中崩溃,事务包装器可以防止丢失数据。
之后跑VACUUM ANALYZE
。或者(通常在走完路线后不需要)使其达到最小尺寸(采用排他锁)。对于大表考虑替代方案/或类似的:TRUNCATE
VACUUM FULL ANALYZE
CLUSTER
pg_repack
对于小表,简单DELETE
的而不是TRUNCATE
通常更快:
DELETE FROM tbl t
USING del_list d
WHERE t.id = d.id;
阅读手册中的注释部分TRUNCATE
。特别是(正如佩德罗在他的评论中指出的那样):
TRUNCATE
不能用于具有来自其他表的外键引用的表,除非所有此类表也在同一命令中被截断。[...]
和:
TRUNCATE
不会ON DELETE
触发表可能存在的任何触发器。