2014-07-01 27 views
6

Ich habe eine sehr große Redshift-Datenbank. Die Datensätze haben keine eindeutigen Schlüssel oder IDs. Ich möchte alle Duplikate mit der effizientesten Abfrage entfernen.Entfernen Sie alle Duplikate aus Redshift-Datenbank

Andere Stackoverflow-Fragen zu typischen SQL-Datenbanken schlugen vor, die Tabelle zu kopieren und die Duplikate während dieses Prozesses zu überspringen, aber das scheint für eine riesige Rotverschiebungsdatenbank nicht optimal zu sein.

Gibt es bessere Lösungen da draußen?

+0

eine der Antworten auf http://stackoverflow.com/questions/15170701/amazon-redshift-keys-are-not-enforced-how-to-prevent- duplicate-data zeigt, wie man die Duplikate identifiziert, löscht und dann eine Instanz von jedem zurück in die Haupttabelle einfügt. – mc110

+0

Leider ist das nicht genau dasselbe, er hatte Primärschlüssel, die nicht erzwungen wurden, während ich in dieser Tabelle keinen Primärschlüssel habe. Ich muss doppelte Datensätze entfernen, basierend auf der Tatsache, dass die Werte für alle Attribute für jeden Datensatz identisch sind. Dies wäre wahrscheinlich nicht sehr schwierig für jemanden mit schärferen Fähigkeiten als ich. – johncorser

+0

können Sie nicht etwas Ähnliches wie Disqs Antwort tun, wo Sie nach allen Zeilen gruppieren, um die Duplikate zu finden und diese in eine temporäre Tabelle einzufügen (Sie erhalten nur eine Instanz von jedem aufgrund der Gruppierung), löschen Sie übereinstimmende Zeilen in der Haupttabelle, dann einfügen zurück aus der Temp-Tabelle? – mc110

Antwort

12

Eine Sache zu beachten mit Redshift ist, dass gelöschte Datensätze nur tatsächlich "weich" gelöscht werden, bis VACUUM ausgeführt wird.
- Sie bleiben in der Tabelle markiert als zu-ignoriert
- Sie sind erst nach einer Vakuum-

ein Vakuum mit Löschungen auf einem großen Tisch jedoch gelöscht durch sie verstreut sehr oft ist tatsächlich langsamer als eine "tiefe Kopie". (Duplizieren der Daten in einer anderen Tabelle, indem GROUP BY oder DISTINCT die Duplikate zu beseitigen, TRUNCATE die ursprüngliche Tabelle und die Daten wieder einsetzen oder die Original-Tabelle löschen und die neue Tabelle umbenennen.)

Dies ist eine allgemeine rational Denn warum profitierst du vielleicht von etwas, das sich wie der "langsame" Prozess anfühlt.


Auch, wenn zwei Reihen wirklich identisch sind, dann gibt es keine Möglichkeit, (per Definition) eindeutig eine Zeile zu identifizieren. In diesem Fall können Sie nicht unterscheiden zwischen einem zu behaltenden und einem zu löschenden.

Ein "Trick" in anderen RDBMS ist ROW_NUMBER() innerhalb eines gemeinsamen Tabellenausdrucks zu verwenden und dann aus diesem CTE zu löschen. (Mit dem CTE werden die eindeutigen Bezeichner erstellt, mit denen Sie einzelne Zeilen angeben können, die beibehalten oder gelöscht werden sollen.) Leider unterstützt Redshift derzeit nicht das Löschen aus einem CTE.

Bis sich dies ändert, tiefe Kopie(Kopieren in einer separaten Tabelle, während GROUP BY oder DISTINCT verwenden) ist derzeit die einzige Möglichkeit.

Trotzdem kann die Deep Copy Option in Redshift noch mehr gültig sein, auch wenn das Löschen von einem CTE jemals möglich wird.


EDIT:

Korrektur:

Wenn jede Zeile in einer Rotverschiebung der Tabelle gelöscht worden ist, jede nachfolgende VACUUM wird erneut verarbeiten die gesamte Tabelle (unabhängig davon, wo die gelöschten Zeilen sind oder wie viele gelöschte Zeilen es gibt).

(Es ist ausgeklügelter, wenn VACUUMing nach einem INSERT, aber unten rechts hässlich nach einem DELETE.)

habe bemerkt, ich auch, dass eine tiefe Kopie weniger Speicherplatz als einVACUUM verwendet. (die nur meine Aufmerksamkeit kam, als wir aus Festplattenspeicher lief ...)


EDIT:

Codebeispiel:

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; 

Or ...

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; 


Zugehöriger Link: https://docs.aws.amazon.com/redshift/latest/dg/performing-a-deep-copy.html

+0

Würde es Ihnen etwas ausmachen, Ihren Post so zu bearbeiten, dass er ein generisches Code-Snippet/Beispiel enthält, mit dem dies erreicht wird (mit der Gruppe "by or distinct")? – johncorser

+0

Vielen Dank, Mann :) –

+2

Sie können es ohne DDL tun. Sie können auch Sortierschlüssel und distkey neu definieren, während Sie gerade dabei sind: 'Tabelle tableName_unique sortkey (col1, col2) distkey (col1) as select * from verschiedener Tabellennamen erstellen;' –

Verwandte Themen