如何加快删除没有行的文档
Posted
技术标签:
【中文标题】如何加快删除没有行的文档【英文标题】:How to speed up deleting documents without rows 【发布时间】:2015-09-26 07:39:33 【问题描述】:文档标题在 omdok 表中:
create table omdok ( dokumnr serial primary key, ... );
文档行在 omrid 表中
CREATE TABLE omrid
(
id serial NOT NULL,
reanr serial NOT NULL,
dokumnr integer NOT NULL,
CONSTRAINT omrid_pkey PRIMARY KEY (id),
CONSTRAINT omrid_dokumnr_fkey FOREIGN KEY (dokumnr)
REFERENCES omdok (dokumnr) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY IMMEDIATE,
....
);
omdok 中没有 omrid 子行的记录需要删除
我试过了
delete from omdok where dokumnr not in (select dokumnr from omrid)
查询它目前正在运行 15 小时并且仍在运行。 postgres.exe 一直在使用 50% 的 CPU(这是 2 核 CPU)。
explain delete from omdok where dokumnr not in (select dokumnr from omrid)
返回:
"Delete (cost=0.00..21971079433.34 rows=220815 width=6)"
" -> Seq Scan on omdok (cost=0.00..21971079433.34 rows=220815 width=6)"
" Filter: (NOT (SubPlan 1))"
" SubPlan 1"
" -> Materialize (cost=0.00..94756.92 rows=1897261 width=4)"
" -> Seq Scan on omrid (cost=0.00..77858.61 rows=1897261 width=4)"
如何快速删除没有子行的父母?
此命令会完成还是 postgres 挂起?
目前运行 15 小时。需要多少小时才能完成?
如何加快查询速度?
使用
PostgreSQL 9.0.1, compiled by Visual C++ build 1500, 64-bit
Windows 2003 x64 server with 4 GB RAM.
【问题讨论】:
【参考方案1】:您没有以任何方式限定您的 DELETE
查询,因此将 220,815 个文档与 1,897,261 个文档行进行比较。这需要时间。
最简单的优化是在文档行上使用DISTINCT
子句,这应该会使omrid
中的行减少8 倍左右:
DELETE FROM omdok WHERE dokumnr NOT IN (SELECT DISTINCT dokumnr FROM omrid);
一个可能更快的解决方案是首先识别没有行的文档,然后删除这些行:
WITH docs0rows AS (
SELECT dokumnr
FROM omdok d
LEFT JOIN (SELECT DISTINCT dokumnr FROM omrid) dr ON dr.dokumnr = d.dokumnr
WHERE dr.dokumnr IS NULL
)
DELETE FROM omdok d
USING docs0rows zero
WHERE d.dokumnr = zero.dokumnr;
免责声明:在运行此命令之前对其进行测试以查看将删除哪些行。
【讨论】:
它会导致错误列引用“dokumnr”不明确。可能 omdok.dokumnr 应该在 delete where 子句中使用。 using 子句在 9.0 中有效还是应该从 ? 在DELETE
语句中,您使用USING
而不是FROM
来指定额外的表来构建过滤条件子句。适用于所有版本。答案已更正。
为什么在 delete 中使用别名 d 和 zero?删除它们并改用表名是否安全?【参考方案2】:
另一种选择是在omrid(dokumnr)
上简单地创建一个索引:
create index idx_omrid_dokumnr on omrid(dokumnr);
这应该会加快原始查询中not in
的处理速度。
【讨论】:
psql-genral 邮件列表建议替换为delete from omdok where not exists(select 1 from omrid where omdok.dokumnr = omrid.dokumnr);
@Andrus。 . .我也更喜欢not exists
,但我认为该索引适用于任何一种表述。以上是关于如何加快删除没有行的文档的主要内容,如果未能解决你的问题,请参考以下文章