Ho una tabella DB che consiste di 2,5 miliardi di record. Ci sono duplicati per un totale di 11 milioni. Qual è il modo più veloce per eliminare questi 11 milioni di record?Come eliminare più velocemente?
risposta
Prima mettere un indice sulla colonna o le colonne che definiscono e contengono i valori duplicati,
Poi, assumimg la tabella ha una chiave primaria (PK),
Delete Table T Where PK <>
(Select Min(PK) From Table
Where ColA = T.ColA
... for each column in set defined above
And ColB = T.ColB)
NOTA: potrebbe anche usare Max (PK), tutto quello che stai facendo è identificare un singolo record da non eliminare da ogni serie di duplicati
MODIFICA: per eliminare l'uso estensivo del log delle transazioni e della partizione UNDO, è possibile memorizzare i valori che sono dupes in una tabella temporanea e quindi eliminare i duplicati f o ciascuna coppia all'interno di una singola transazione ...
Supponendo solo una colonna (chiamare ColA, un numero) definisce i dupes ...
Create Table Dupes (ColA Number)
Insert Dupes(ColA)
Select Distinct ColA
From Table
Group By ColA
Having Count(*) > 1
recordExists Number := 0 ;
ColAValue Number;
Select Case When Exists (Select Count(*) From Dupes)
Then 1 Else 0 End Into recordExists From Dual;
While recordExists = 1
Loop
Select (Select Max(ColA) From Dupes)
Into ColAValue From Dual;
Begin Transaction
Delete Table T
Where ColA = ColAValue
And pk <> (Select Min(Pk) From Table
Where ColA = ColAValue);
Delete Dupes Where ColA = ColAValue;
Commit Transaction;
Select Case When Exists (Select Count(*) From Dupes)
Then 1 Else 0 End Into recordExists From Dual;
End Loop;
Non testato, così sintassi può neeed massaggio ...
Se si è certi di non alterare l'integrità dei dati (integrità referenziale), disabilitare i vincoli (indici, altri vincoli), eseguire l'eliminazione, quindi abilitare i vincoli. Devi prima provare, per vedere se l'aggiornamento degli indici durante l'attivazione richiede meno tempo rispetto all'eliminazione con loro abilitata.
Anche l'ottimizzazione delle query può essere d'aiuto, ma senza conoscere ulteriori dettagli, stiamo discutendo in teoria.
Non lasciare cadere l'indice sulle colonne che si stanno utilizzando per trovare duplicati, facendo ripetute scansioni di tabelle complete di 2.500.000.000 di righe sarà molto molto lento. – Richard
Non eseguirà scansioni di tabelle ripetute, eseguirà hash semi join se non ci sono indici. – Quassnoi
DELETE
FROM mytable
WHERE rowid IN
(
SELECT rowid
FROM (
SELECT rowid, ROW_NUMBER() OVER (ORDER BY dupfield) rn
FROM mytable r
)
WHERE rn > 1
)
o forse anche questo:
DELETE
FROM mytable mo
WHERE EXISTS
(
SELECT NULL
FROM mytable mi
WHERE mi.dup_field = mo.dup_field
AND mi.rowid <> mo.rowid
)
Entrambe queste query userà abbastanza efficiente HASH SEMI JOIN
, quest'ultimo sarà più veloce se non v'è alcun indice su dup_field
.
Si può essere tentati di copiare le righe, ma è da notare che molto più REDO
e UNDO
informazioni saranno generati durante la copia di file 2G
rispetto a quando la cancellazione 11M
.
come sono le prestazioni di un aggiornamento come questo quando la dimensione della tabella è di 2,5 miliardi? –
Ho la sensazione che questa query sia lenta, ma potrebbe raggiungere ciò di cui l'OP ha bisogno. Può essere riscritto come join? –
Ci sarà un ordinamento su 'dupfield' (se non ci sono indici su di esso), che può richiedere molto tempo. Il join su 'rowid' sarà un' HASH SEMI JOIN', che è una questione di minuti su '2G' contro' 11M' righe. Cancellare stesso richiederà anche decine di minuti, principalmente per generare 'REDO' e' UNDO'. – Quassnoi
Eliminare un duplicato da molti è un lavoro complicato e con tutti questi record si ha un problema.
Un'opzione è di trasformare il problema in testa e copiare i record che si desidera conservare in una nuova tabella. È possibile utilizzare la sintassi CREATE TABLE AS SELECT DISTINCT ... NOLOGGING
, che copierà i record deduplicati senza utilizzare il log delle transazioni, che è molto più veloce. Una volta che la tua nuova tabella è popolata, cancella/rinomina la vecchia e rinominala nella nuova posizione.
Oh, e ricordarsi di dargli un indice univoco nella nuova tabella per cui questo non accada di nuovo.
La morale della storia è ... mai uso DELETE per sbarazzarsi di un gran numero di record, è spaventosamente lento perché deve memorizzare tutti i record eliminati nel redo log. Copia-e-switch o TRUNCATE.
... e potresti applicare lo stesso algoritmo al team che ha prodotto il prodotto che ha consentito solo 11.000.000 di righe duplicate ;-) Keith. – corlettk
+1 per questa risposta. Sarei sicuramente tentato di creare una nuova copia del tavolo e inserirla in quello. La cosa fondamentale che aggiungerei è non inserire alcun indice su quella tabella secondaria fino a quando non hai copiato i dati - non vuoi che l'inutile hit di questo debba mantenere gli indici in alto durante l'inserimento dei dati.Mi piace anche questo approccio perché ha una rete di sicurezza extra: non devi liberarti del vecchio tavolo finché non sei sicuro al 100% di avere tutti i dati giusti. – AdaTheDev
sarebbe interessante confrontare il tempo necessario per copiare 2.489 miliardi di record vs eliminare 11 milioni, usando gli stessi predicati –
Se eliminare le righe esistenti o creare una nuova tabella corretta e rilasciare quella precedente è più veloce dipende da molti fattori. 11 milioni di righe sono molte, ma è solo lo 0,5% del numero totale di righe nella tabella. È abbastanza probabile che la ricomposizione dello & calo possa essere molto più lenta dell'eliminazione, a seconda del numero di indici presenti nella tabella di origine, nonché del punto in cui le righe che devono essere eliminate esistono nelle pagine di dati.
Quindi c'è il problema se la tabella di origine è attiva o meno. Se ci sono inserimenti & in corso mentre è in corso la pulizia, la copia & non funzionerà senza una buona quantità di codice aggiuntivo per sincronizzare la tabella dopo il fatto.
Infine, perché è necessario che questa operazione sia "veloce"? È perché il sistema deve essere offline mentre si sta verificando il processo? È possibile scrivere una procedura che rimuove i duplicati mentre il sistema è attivo, ma non ha alcun impatto sul resto del sistema in termini di consumo di annullamento. Abbiamo risolto questo problema in passato dalla prima crei una query che raccoglie le chiavi primarie delle righe da rimosso in una seconda tabella, in questo modo:
INSERT
INTO RowsToDeleteTable
SELECT PKColumn
FROM SourceTable
WHERE <conditions used to find rows to remove>
CREATE UNIQUE INDEX PK_RowsToDelete ON RowsToDeleteTable (PKColumn);
allora abbiamo un blocco PL/SQL che o loop sopra le righe in un cursore in questo modo:
BEGIN
FOR theRow IN (SELECT PKColumn FROM RowsToDeleteTable ORDER BY 1) LOOP
<delete source table for theRow.PKColumn)
<optionally wait a bit>
commit;
END LOOP;
END;
o fa qualcosa di simile:
BEGIN
FOR theRow IN (SELECT MIN(PKColumn) FROM RowsToDeleteTable) LOOP
<delete source table for theRow.PKColumn)
<optionally wait a bit>
DELETE RowsToDeleteTable
WHERE PKColumn = theRow.PKColumn;
commit;
END LOOP;
END;
il looping e "SELECT MAX" è ovviamente meno efficiente, ma ha il vantaggio di permettere che si t o seguire l'avanzamento dell'operazione di cancellazione. Inseriamo un po 'di codice di attesa nel ciclo per permetterci di controllare la vigorosa operazione di mietitura.
La creazione iniziale di RowsToDeleteTable avviene molto rapidamente e si ha il vantaggio di consentire al processo di durare quanto si desidera. In questo caso, i "buchi" lasciati nelle estensioni dalle eliminazioni non saranno troppo negativi, dal momento che stai cancellando una percentuale così piccola dei dati totali.
- 1. Come creare indici più velocemente?
- 2. Come elencare le directory più velocemente?
- 3. Come caricare Android WebView più velocemente?
- 4. Come posso sottrarre questi elenchi più velocemente?
- 5. Come caricare i frammenti più velocemente?
- 6. Come eliminare più righe?
- 7. Il php funziona più velocemente senza avvertimenti?
- 8. UPDATE più velocemente in SQLite + BEGIN TRANSACTION
- 9. query più velocemente con l'attributo top
- 10. Compilare più velocemente in Visual Studio 2005
- 11. Come eliminare gli eventi da una coda Amazon SQS (Simple Queue Service) molto velocemente?
- 12. Come rendere l'IDE eclisse per costruire più velocemente
- 13. Come far funzionare un sito web più velocemente?
- 14. Come posso aprire questa cartella di lavoro VBA più velocemente?
- 15. Come inserire i dati il più velocemente possibile con Hibernate
- 16. Come eliminare in modo sicuro più puntatori
- 17. Come eliminare più entità db con Nhibernate?
- 18. Come eliminare più colonne in postgresql
- 19. Come eliminare i dati da più tabelle?
- 20. eliminare più righe nella YII2
- 21. elemento con scrollLeft scorre più velocemente del resto del documento
- 22. Come eseguire velocemente gli screenshot in Java?
- 23. Questa ricerca di ampiezza può essere effettuata più velocemente?
- 24. Le pagine Web valide si caricano più velocemente?
- 25. Ordina più velocemente nel racket utilizzando tabella hash
- 26. Perché la mia CPU improvvisamente funziona il doppio più velocemente?
- 27. Questa query SQLite può essere eseguita molto più velocemente?
- 28. Come decodificare velocemente il codice huffman?
- 29. Ruby o altre lingue funzioneranno più velocemente con Parrot?
- 30. R: Perché l'approccio [[]] per inserire una lista più velocemente di $?
Solo per visualizzare le prestazioni del sistema, la query per ottenere il conteggio delle righe duplicate ha richiesto 1 ora e 40 minuti. –
Penso che l'OP abbia cancellato il suo account. – Shimmy
Grazie ragazzi! Ho dovuto copiare i record univoci in una tabella, troncare la tabella originale e copiare i dati univoci. – Chattz