Algoritmi di ordinamento che funzionano su grandi quantità di dati


12

Sto cercando algoritmi di ordinamento che possano funzionare su una grande quantità di dati, cioè che possano funzionare anche quando l'intero set di dati non può essere conservato nella memoria principale contemporaneamente.

L'unico candidato che ho trovato finora è unire l'ordinamento: è possibile implementare l'algoritmo in modo tale da scansionare il tuo set di dati ad ogni unione senza tenere tutti i dati nella memoria principale contemporaneamente. La variazione del tipo di unione che ho in mente è descritta in questo articolo nella sezione Uso con unità nastro .

Penso che questa sia una buona soluzione (con complessità O (nx log (n)) ma sono curioso di sapere se ci sono altri algoritmi di ordinamento (forse più veloci) che possono funzionare su grandi set di dati che non rientrano nella memoria principale.

MODIFICARE

Ecco alcuni dettagli in più, come richiesto dalle risposte:

  • I dati devono essere ordinati periodicamente, ad esempio una volta al mese. Non è necessario inserire alcuni record e i dati devono essere ordinati in modo incrementale.
  • Il mio file di testo di esempio è di circa 1 GB di testo UTF-8, ma volevo risolvere il problema in generale, anche se il file fosse, diciamo, 20 GB.
  • Non si trova in un database e, a causa di altri vincoli, non può esserlo.
  • I dati vengono scaricati da altri come file di testo, ho il mio codice per leggere questo file di testo.
  • Il formato dei dati è un file di testo: i caratteri di nuova riga sono separatori di record.

Un possibile miglioramento che avevo in mente era quello di dividere il file in file abbastanza piccoli da essere ordinati in memoria e infine unire tutti questi file usando l'algoritmo che ho descritto sopra.


1
Che tipo di dati? Set di dati diversi possono significare algoritmi diversi che si adattano meglio al tuo scopo.
whatsisname

È un file di testo e devo ordinare le linee. Le righe non hanno una lunghezza fissa ma la lunghezza non varia troppo (circa 50 caratteri per record).
Giorgio

3
Non conosco il tuo ambiente o i tuoi vincoli, ma userei un database per l'ordinamento ogni volta che è possibile. Questo perché è quasi al 100% a prova di errore e sarà molto più efficiente del mio codice.
NoChance,

Sto lavorando su Linux / Java. Ho implementato il tipo di unione e sembra funzionare abbastanza bene. L'ordinamento di diversi milioni di linee richiede un po 'di tempo, ma devo farlo solo una volta ogni tanto.
Giorgio

@Giorgio, è un bene che tu abbia implementato un tale algoritmo. Per il lavoro di produzione, suggerisco ancora di utilizzare un database. Non solo per la velocità ma anche per affidabilità e facilità di manutenzione.
NoChance,

Risposte:


13

Il riferimento canonico su ordinamento e ricerca è Knuth, Vol. 3 . Inizia lì.

Il libro è stato originariamente riscritto quando i computer erano molto più piccoli e più lenti di quanto non lo siano ora, il che ha reso le tecniche di ordinamento a memoria insufficiente più importanti di quanto si pensi oggi.


2
Grazie per il riferimento: sono quasi sicuro di trovare materiale interessante nel libro di Knuth. Non sono sicuro che le tecniche di ordinamento di memoria insufficiente non siano rilevanti oggi. Forse non per attività quotidiane comuni, ma posso immaginare che ci siano ancora molte situazioni in cui è necessario elaborare set di dati molto grandi.
Giorgio,

Gli algoritmi di Knuth sono sempre utili. Ad esempio, un ordinamento di fusione con un buffer di ordinamento dell'heap può essere molto efficace e MOLTO facile da implementare.
Sulthan,

4
Non è una risposta molto utile perché il materiale indicato non è gratuito. Per l'OP, suggerisco di cercare su Google una risposta. Non è necessario sborsare $ 50 dollari per ottenere un libro quando questo tipo di informazioni è possibile trovare scavando sul Web. Naturalmente, puoi probabilmente scaricarlo gratuitamente anche da ( ahem ) determinati siti. Non merita una risposta accettata.
Thomas Eding,

1
@ThomasEding, ci sono queste cose chiamate "librerie", che contengono grandi quantità di questi obsoleti dispositivi di archiviazione e recupero delle informazioni chiamati "libri". Le "biblioteche" rendono i "libri" disponibili per PRESTITO GRATUITO. Se la tua "biblioteca" particolare non ha il "libro" che cerchi, offrono anche un servizio GRATUITO chiamato "prestito interbibliotecario", che consente alla "biblioteca" di prendere in prestito il "libro" da un'altra "biblioteca", in modo che possano prestalo a te.
John R. Strohm,

6

L'unione R-Way esterna come nel sortcomando UNIX è una buona alternativa. Dalla tua formulazione, non sono sicuro che si tratti dell'algoritmo che intendevi con "unisci ordine" e, se non lo conosci, dai un'occhiata.


Grazie. L'unione R-Way esterna sembra diversa da ciò che avevo in mente. Lettura interessante
Giorgio

4

Senza ulteriori dettagli "Unisci ordinamento" è probabilmente la risposta migliore che otterrai, tuttavia puoi implementare qualcosa di molto più intelligente a seconda delle tue esigenze.

Ad esempio, puoi semplicemente creare un indice in memoria del file e quindi copiare tutti i valori contemporaneamente, memorizzando nella cache la posizione di vari valori chiave? 1/2 si adatta alla memoria contemporaneamente o 1/1000000? Se è il secondo, potresti non essere in grado di adattare un indice in memoria, se il primo è possibile ordinare entrambe le metà in modo più efficiente, quindi unirle in un unico ultimo passaggio.

Inferno, dal momento che non hai specificato che è possibile che i tuoi dati siano tutti in un database, in tal caso puoi semplicemente creare una tabella di indice e chiamarla bene (suppongo che non sia così, ma sottolineo solo che la tua situazione è fondamentale per risolvere un problema complicato come questo).

Se vuoi farlo solo una volta e stai cercando un trucco molto veloce, sembra che l'ordinamento di unione esterno sarebbe un buon inizio se stai eseguendo unix (dal momento che è apparentemente integrato)

Se devi mantenerlo in ordine e aggiungi sempre un singolo record, sarà necessario un ordinamento di inserimento (l'aggiunta di un singolo record ai dati ordinati è sempre un ordinamento di inserimento).

Puoi controllare il codice che "Legge" i dati? In tal caso, molte forme di indicizzazione (anziché l'ordinamento spostando i dati sul disco) aiuteranno A MOLTO (sarà effettivamente un requisito assoluto).

Così:

  • Sul posto o più file?
  • Una volta, periodicamente o tenerlo sempre ordinato?
  • Quanto più grande della memoria (quanti carichi di memoria devono superare l'intero set di dati)?
  • È in un database? Può essere?
  • Controlli il codice che legge i dati o altri scaricheranno direttamente un file?
  • Formato del file? (Testo? Record fisso?)
  • Altre circostanze speciali di cui non ho chiesto?

Grazie per la risposta. Cosa intendi con "Sul posto o record multiplo"?
Giorgio

Scusa, dovrei aver letto la mia risposta come prova - intendevo più file. Sul posto implica praticamente dimensioni dei record fisse e indicizzazione a quel punto probabilmente si vorrebbe un database.
Bill K,

No, non è presente: i record non hanno dimensioni fisse. Uso quattro file temporanei per la mia attuale implementazione.
Giorgio

Riesci a interpretare l'output con il codice o deve essere in un formato specifico (file di testo semplice?) Ogni quanto deve essere ordinato - ogni volta che viene aggiunto qualcosa o solo occasionalmente? Quando viene aggiunto qualcosa, viene semplicemente aggiunto alla fine o puoi scrivere il codice che lo aggiunge?
Bill K

Ogni riga può essere analizzata in un record (il file è un file CSV) ma la maggior parte dei campi sono di testo. Deve essere ordinato una volta ogni tanto (ad esempio ogni mese) e ci vuole circa 1 ora per ordinare con la mia attuale implementazione. Per l'inserimento di una riga ho potuto scrivere il codice che inserisce la riga nel posto giusto: con il codice che ho finora mi occorrerebbero 20 minuti per scrivere un tale strumento.
Giorgio

3

Se vuoi davvero una soluzione scalabile dovresti dare un'occhiata a TeraSort, l'implementazione di ordinamento standard con map-riduc; maggiori dettagli su StackOverflow .


1
+1: link interessante. L'unione di ordinamento non è un esempio di mappa / riduzione, dove mappa corrisponde agli elenchi secondari di ordinamento e riduzione corrisponde all'unione?
Giorgio,

Può essere visto così, ma puoi usare Hadoop per fare questo per te invece di scriverlo da solo.
m3th0dman,

1

Potresti essere interessato a un tipo di bucket . Le prestazioni medie del caso sono tempi lineari.

= O (n + d) n: numero di elementi e d = lunghezza del numero più grande se hai un'intuizione sui tuoi dati, ad es. Se sai quante "cifre" sono lunghe il tuo numero più grande. Quindi se hai 2 milioni di numeri a 6 cifre => 0 (n) quindi lineari.


0

Utilizzare un algoritmo di ordinamento di tipo merge esterno (se i dati sono continui) o un ordinamento bucket con ordinamento conteggio come implementazione dell'ordinamento per bucket (se i dati sono discreti e distribuiti uniformemente).

Probabilmente l'approccio migliore è quello di creare il proprio file indice / mapping se l'incremento è piccolo.

  1. In qualche modo ordina il tuo "database"
  2. Assegna un numero intero a ogni voce (1, 2, 3, 4, ..., n) (meglio: usa alcuni indici sparsi)
  3. Quando si aggiunge un incremento, basta trovare uno spazio in cui il numero a sinistra è minore o uguale e il numero a destra è maggiore o uguale (non dovrebbe essere difficile con alcune versioni modificate di una ricerca binaria)
  4. Inserisci, mentre gli spazi sono sufficientemente grandi, in caso contrario: basta reindicizzare (non ordinare mai più) :-)

0

Ho appena costruito alcune strutture astratte chiamate big queue e big array per semplificare l'ordinamento e la ricerca di big data su una singola macchina con memoria limitata. Fondamentalmente, l'algoritmo utilizzato è simile a quello che hai menzionato sopra - ordinamento di unione esterna.

Posso ordinare 128 GB di dati (ogni elemento 100 byte) in 9 ore su una singola macchina, e quindi cercare binariamente i dati ordinati quasi senza tempo.

Ecco un post su come cercare i big data usando la mia grande coda open source e le strutture di big array.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.