2014-07-01 69 views
6

我有一個非常大的Redshift數據庫。記錄沒有唯一的密鑰或ID。我想刪除所有可能的最有效查詢的重複項。從Redshift數據庫中刪除所有重複項

有關典型sql數據庫的其他stackoverflow問題建議複製表和跳過重複在該過程中,但這似乎是一個巨大的紅移數據庫不理想。

有更好的解決方案嗎?

+0

的答案之一http://stackoverflow.com/questions/15170701/amazon-redshift-keys-are-not-enforced-how-to-prevent-重複數據顯示如何識別重複項,刪除它們,然後將每個重複項的一個實例插入到主表中。 – mc110

+0

不幸的是,這不完全相同,他有主鍵沒有執行,而我沒有在這張表中的主鍵。我必須根據每個記錄的所有屬性值都相同的事實刪除重複的記錄。對於那些擁有比我更強大的SQL技能的人來說,這可能不會很困難。 – johncorser

+0

難道你不能做類似於disq的答案嗎?你按照所有行進行分組以找到重複項並將它們插入臨時表(由於分組,只會獲得每個實例的一個實例),刪除主表中的匹配行,然後從臨時表中插回來? – mc110

回答

12

用Redshift記住的一件事是刪除的記錄實際上只是「軟」刪除,直到VACUUM運行。
- 他們保留在表中,標記爲要被忽略
- 他們一個真空後會刪除只

然而,通過它散落在一張大桌子真空 - 刪除是非常往往比實際慢一個「深度複製」。 (複製的數據到另一個表,使用GROUP BYDISTINCT來消除重複,TRUNCATE原始表和重新插入數據或刪除原始表和重命名新表中。)

這是一般的合理爲什麼你可能真的從「慢」的過程中受益。


而且,如果兩行真的是相同的,則沒有辦法(定義)來唯一地標識一行。既然如此,就不能區分要保留的和要刪除的。

其他RDBMS中的一個「技巧」是在公用表表達式中使用ROW_NUMBER(),然後從該CTE中刪除。 (使用CTE創建唯一標識符,允許您確定要保留或刪除的單個行。)不幸的是,Redshift目前不支持從CTE中刪除。

直到這個變化,深複製(同時使用GROUP BYDISTINCT複製到一個單獨的表)是目前唯一的選擇。

即便如此,深度複製選項仍然可以在Redshift中更有效,即使從CTE刪除變得可能。


編輯:

校正:

如果在紅移表任何行已被刪除,任何後續VACUUM將重新處理整個(不管被刪除的行在哪裏,或者有多少刪除的行)

(在INSERT後面執行VACUUMing,但在DELETE後面執行右下角時會更復雜。)

我也注意到一個深複製使用超過真空更少的磁盤空間。 (當我們跑出來的磁盤空間,其中僅來到了我的注意...)


編輯:

代碼示例:

CREATE TABLE blah_temp (
    <Exactly the same DDL as the original table, especially Distribution and Sort keys> 
) 
; 

INSERT INTO 
    blah_temp 
SELECT DISTINCT 
    * 
FROM 
    blah 
; 

DROP TABLE blah; 

ALTER TABLE blah_temp RENAME TO blah; 

或者...

CREATE TABLE blah_temp (
    <Exactly the same DDL as the original table, especially Distribution and Sort keys> 
) 
; 

INSERT INTO 
    blah_temp 
SELECT 
    * 
FROM 
    blah 
GROUP BY 
    a, b, c, d, e, f, g, etc 
; 

TRUNCATE TABLE blah; 

INSERT INTO 
    blah 
SELECT 
    * 
FROM 
    blah_temp 
; 

DROP TABLE blah_temp; 


相關鏈接:https://docs.aws.amazon.com/redshift/latest/dg/performing-a-deep-copy.html

+0

你是否介意編輯你的帖子以包含一個通用的代碼片段/例子來完成這個(使用group by或distinct)? – johncorser

+0

非常感謝,男士:) –

+2

你可以不用DDL。你也可以重新定義sortkeys和distkey,當你在它時: 'create table tableName_unique sortkey(col1,col2) distkey(col1) as select distinct * from tableName;' –