Ant*_*eco 63 sql postgresql bigdata postgresql-performance sql-delete
我需要从PG数据库中删除大约200万行.我有一个我需要删除的ID列表.但是,我尝试这样做的任何方式都需要几天时间.
我尝试将它们放在一个表中,并在100个批次中进行.4天后,这仍然在运行,只删除了297268行.(我必须从ID表中选择100个id,删除该列表中的IN,从ids表中删除我选择的100个).
我试过了:
DELETE FROM tbl WHERE id IN (select * from ids)
Run Code Online (Sandbox Code Playgroud)
那也是永远的.很难判断多久,因为我看不到它的进展直到完成,但查询仍然在2天后运行.
当我知道要删除的特定ID时,只需要寻找从表中删除的最有效方法,并且有数百万个ID.
Erw*_*ter 84
这一切都取决于......
删除所有索引(删除所需的ID除外)
之后重新创建(=比索引的增量更新快得多)
检查您是否具有可以安全地暂时删除/禁用的触发器
外键引用你的表吗?他们可以删除吗?暂时删除了?
根据您的autovacuum设置,它可能有助于VACUUM ANALYZE在操作之前运行.
假设没有对所涉及的表进行并发写访问,或者您可能必须独占锁定表,或者此路由可能根本不适合您.
根据您的设置,填充数据库手册相关章节中列出的一些要点也可能有用.
如果你删除表的大部分,其余部分适合RAM,最快和最简单的方法是:
SET temp_buffers = '1000MB'; -- or whatever you can spare temporarily
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
TRUNCATE tbl; -- empty table - truncate is very fast for big tables
INSERT INTO tbl
SELECT * FROM tmp; -- insert back surviving rows.
Run Code Online (Sandbox Code Playgroud)
这样您就不必重新创建视图,外键或其他依赖对象.阅读temp_buffers手册中的设置.只要表适合内存或至少大部分内存,此方法就很快.请注意,如果服务器在此操作过程中崩溃,则可能会丢失数据.您可以将所有内容包装到事务中以使其更安全.
ANALYZE之后运行.或者,VACUUM ANALYZE如果您没有采用截断路线,或者VACUUM FULL ANALYZE您希望将其降至最小尺寸.对于大表,考虑替代品CLUSTER/ pg_repack:
对于小型表,简单DELETE而不是TRUNCATE通常更快:
DELETE FROM tbl t
USING del_list d
WHERE t.id = d.id;
Run Code Online (Sandbox Code Playgroud)
阅读手册中的" 注释"部分TRUNCATE.特别是(正如佩德罗在他的评论中指出的那样):
TRUNCATE不能在具有其他表的外键引用的表上使用,除非所有这些表也在同一命令中被截断.[...]
和:
TRUNCATE不会ON DELETE触发表可能存在的任何触发器.
我自己刚刚遇到这个问题,对我来说,到目前为止,最快的方法是将WITH查询与USING结合使用
基本上,WITH 查询会创建一个临时表,其中包含要从要删除的表中删除的主键。
WITH to_delete AS (
SELECT item_id FROM other_table WHERE condition_x = true
)
DELETE FROM table
USING to_delete
WHERE table.item_id = to_delete.item_id
AND NOT to_delete.item_id IS NULL;
Run Code Online (Sandbox Code Playgroud)
当然,SELECTWITH 查询的内部可以与具有多个联接等的任何其他选择一样复杂。它只需要返回一个或多个列,用于标识目标表中需要删除的项目。
注意:AND NOT to_delete.item_id IS NULL很可能没有必要,但我不敢尝试。
其他需要考虑的事情是
| 归档时间: |
|
| 查看次数: |
45769 次 |
| 最近记录: |