2014-07-01 15 views
6

Ho un database Redshift molto grande. I record non hanno chiavi o ID univoci. Mi piacerebbe rimuovere tutti i duplicati con la query più efficiente possibile.Rimuovi tutti i duplicati dal database Redshift

Altre domande di stackoverflow sui tipici database sql suggerivano di copiare la tabella e saltare i duplicati durante quel processo, ma ciò sembra non ottimale per un gigantesco database redshift.

Qualche soluzione migliore là fuori?

+0

una delle risposte a http://stackoverflow.com/questions/15170701/amazon-redshift-keys-are-not-enforced-how-to-prevent- i dati duplicati mostrano come identificare i duplicati, eliminarli, quindi inserire un'istanza di ogni retro nella tabella principale. – mc110

+0

Sfortunatamente questo non è esattamente lo stesso, ha avuto chiavi primarie che non sono state applicate, mentre non ho nessuna chiave primaria in questa tabella. Devo rimuovere i record duplicati in base al fatto che i valori di tutti gli attributi per ogni record sono identici. Questo probabilmente non sarebbe molto difficile per qualcuno con abilità sql più acute di me. – johncorser

+0

non si può fare qualcosa di simile alla risposta di disq dove si raggruppano tutte le righe per trovare i duplicati e inserirli in una tabella temporanea (si otterrà solo un'istanza di ciascuno dovuta al raggruppamento), eliminare le righe corrispondenti nella tabella principale, quindi inserire di nuovo dalla tabella temporanea? – mc110

risposta

12

Una cosa da tenere a mente con Redshift è che i record eliminati sono solo "soft" eliminati fino a quando non viene eseguito VACUUM.
- rimangono nella tabella, contrassegnato come essere-ignorato
- Sono eliminati solo dopo un vuoto

Tuttavia, un vuoto su un grande tavolo con le eliminazioni sparsi attraverso di essa è molto spesso in realtà più lento di una "Copia profonda". (duplicati i dati in un'altra tabella, utilizzando GROUP BY o DISTINCT per eliminare i duplicati, TRUNCATE dell'originale tavolo e reinserire i dati o eliminare la tabella originale e rinominare la nuova tabella.)

Questa è una generale razionale per il motivo per cui potresti effettivamente beneficiare di ciò che sembra il processo "lento".


Inoltre, se due file sono davvero identici quindi non c'è modo (per definizione) per identificare in modo univoco una riga. In questo caso non è possibile distinguere tra uno da conservare e uno da eliminare.

Un "trucco" in altri RDBMS consiste nell'utilizzare ROW_NUMBER() all'interno di un'espressione di tabella comune e quindi eliminare da tale CTE. (Con il CTE che crea gli identificatori univoci, che consente di identificare le singole righe da conservare o eliminare.) Sfortunatamente, Redshift non supporta attualmente l'eliminazione da un CTE.

Fino a quando questo cambia, copia completa(copia su un tavolo separato durante l'utilizzo GROUP BY o DISTINCT) è attualmente l'unica opzione.

Anche così, l'opzione Deep Copy potrebbe essere più valida in Redshift anche se l'eliminazione da un CTE diventa possibile.


EDIT:

Correzione:

Se qualsiasi riga in una tabella Redshift è stato eliminato, qualsiasi VUOTO successiva sarà rielaborare tabella intera(indipendentemente da dove sono le righe eliminate o quante righe eliminate ci sono).

(È più sofisticato quando si esegue il VACUUM in seguito a un INSERIMENTO, ma in basso a destra in seguito a DELETE.)

Ho anche notato che un copia completa utilizza meno spazio su disco rispetto a VUOTO. (che solo è venuto alla mia attenzione quando siamo a corto di spazio sul disco ...)


EDIT:

Esempio di codice:

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; 


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

+0

Ti dispiacerebbe modificare il tuo post per includere uno snippet/esempio di codice generico che lo compie (utilizzando il gruppo per o distinto)? – johncorser

+0

Grazie mille, amico :) –

+2

Puoi farlo senza DDL. È anche possibile ridefinire sortkeys e distkey mentre si è in esso: 'create table tableName_unique SortKey (col1, col2) distkey (col1) come select * distinta dalla tableName;' –

Problemi correlati