如何加快删除没有行的文档
How to speed up deleting documents without rows
文件 headers 在 omdok table:
create table omdok ( dokumnr serial primary key, ... );
文档行在 omrid 中 table
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 中没有 child 行需要删除
我试过了
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)
returns:
"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)"
- 如何快速删除没有child行的parents行?
- 此命令会完成还是 postgres 挂起?
- 目前是 运行 15 小时。完成需要多少小时?
如何加快此查询?
使用
PostgreSQL 9.0.1, compiled by Visual C++ build 1500, 64-bit
Windows 2003 x64 server with 4 GB RAM.
您没有以任何方式限定您的 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;
免责声明:在 运行 之前测试此命令以查看将删除哪些行。
另一种方法是简单地在 omrid(dokumnr)
:
上创建一个索引
create index idx_omrid_dokumnr on omrid(dokumnr);
这应该会加快您原始查询中 not in
的处理速度。
文件 headers 在 omdok table:
create table omdok ( dokumnr serial primary key, ... );
文档行在 omrid 中 table
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 中没有 child 行需要删除
我试过了
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)
returns:
"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)"
- 如何快速删除没有child行的parents行?
- 此命令会完成还是 postgres 挂起?
- 目前是 运行 15 小时。完成需要多少小时? 如何加快此查询?
使用
PostgreSQL 9.0.1, compiled by Visual C++ build 1500, 64-bit
Windows 2003 x64 server with 4 GB RAM.
您没有以任何方式限定您的 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;
免责声明:在 运行 之前测试此命令以查看将删除哪些行。
另一种方法是简单地在 omrid(dokumnr)
:
create index idx_omrid_dokumnr on omrid(dokumnr);
这应该会加快您原始查询中 not in
的处理速度。