2015-09-26 41 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