如何加快删除没有行的文档

时间:2015-09-26 07:39:34

标签: sql postgresql sql-delete notin

文档标题位于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.

2 个答案:

答案 0 :(得分:1)

您没有以任何方式限定DISTINCT查询,因此将220,815个文档与1,897,261个文档行进行比较。这需要时间。

最简单的优化是在文档行上使用omrid子句,这会使DELETE FROM omdok WHERE dokumnr NOT IN (SELECT DISTINCT dokumnr FROM omrid); 行的行数减少8倍左右:

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;

一个可能更快的解决方案是首先识别没有行的文档,然后删除这些行:

Parent = {
    name: 'Name',
    age: 'Age',
    children:
        [{name: 'Name', age: 'Age'},
        {name: 'Name', age: 'Age'},
        {name: 'Name', age: 'Age'}]
}

免责声明:在运行此命令之前测试此命令以查看将删除哪些行。

答案 1 :(得分:0)

另一种方法是在omrid(dokumnr)上简单地创建一个索引:

create index idx_omrid_dokumnr on omrid(dokumnr);

这可以加快原始查询中not in的处理速度。