2015-09-26 42 views
0

文件头是在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. 

回答

0

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

create index idx_omrid_dokumnr on omrid(dokumnr); 

这应该加快not in的处理原始查询。

+0

psql-genral邮件列表建议用'从omdok删除不存在的地方(从omrid选择1,其中omdok.dokumnr = omrid.dokumnr);' – Andrus

+0

@安德鲁斯。 。 。我更喜欢“不存在”,但我认为这个指数适用于任何一种公式。 –

1

你这样的220815个文档反对1897261个文档行相比,不以任何方式限定您DELETE查询。这需要时间。

使用DISTINCT子句对文档的行,这应该由一个因子8或因此带来的行从omrid向下的最简单的优化:

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; 

免责声明:测试此命令你运行它,看看哪些行将被删除之前。

+0

它导致错误列引用“dokumnr”不明确。可能omdok.dokumnr应该用于删除clauset。在9.0中使用子句工作还是应该从? – Andrus

+0

在'DELETE'语句中,您使用'USING'而不是'FROM'来指定额外的表来构建过滤条件子句。适用于所有版本。答案已更正。 – Patrick

+0

为什么在删除中使用别名d和零?删除它们并使用表名称是否安全? – Andrus