2012-12-22 22 views
5

Sono uno sviluppatore Python con esperienza RDBMS piuttosto buona. Ho bisogno di elaborare una grande quantità di dati (circa 500 GB). I dati sono contenuti in circa 1200 file csv in bucket s3. Ho scritto uno script in Python e posso eseguirlo su un server. Tuttavia, è troppo lento. In base alla velocità attuale e alla quantità di dati, ci vorranno circa 50 giorni per passare attraverso tutti i file (e, naturalmente, la scadenza è BENE prima di quello).Elaborazione di una grande quantità di dati in parallelo

Nota: l'elaborazione è una specie del tipo di materiale ETL di base, niente di terribile. Potrei facilmente inserirlo in uno schema temporaneo in PostgreSQL e quindi eseguire script su di esso. Ma, ancora una volta, dai miei test iniziali, questo sarebbe il modo di rallentare.

Nota: un nuovissimo database PostgreSQL 9.1 sarà la destinazione finale.

Quindi, stavo pensando di provare a far girare una serie di istanze EC2 per provare a eseguirle in batch (in parallelo). Ma non ho mai fatto qualcosa di simile prima, quindi ho cercato idee, ecc.

Ancora una volta, sono uno sviluppatore Python, quindi sembra che Fabric + boto potrebbe essere promettente. Di tanto in tanto ho usato boto, ma mai nessuna esperienza con Fabric.

So che dalla lettura/ricerca questo è probabilmente un ottimo lavoro per Hadoop, ma non lo conosco e non posso permettermi di assumerlo, e la linea del tempo non consente una curva di apprendimento o di assunzione qualcuno. Non dovrei anche, che è un po 'un affare di un tempo. Quindi, non ho bisogno di costruire una soluzione davvero elegante. Ho solo bisogno che funzioni e sia in grado di ottenere tutti i dati entro la fine dell'anno.

Inoltre, so che questo non è un semplice tipo di stackoverflow (qualcosa come "come posso annullare un elenco in python"). Ma quello che spero è che qualcuno lo legga e "dì, faccio qualcosa di simile e uso XYZ ... è fantastico!"

Immagino che quello che sto chiedendo è che qualcuno sa di qualsiasi cosa là fuori che potrei usare per portare a termine questo compito (dato che sono uno sviluppatore Python e non conosco Hadoop o Java - e ho un Tempi ristretti che mi impediscono di apprendere una nuova tecnologia come Hadoop o di imparare una nuova lingua)

Grazie per la lettura. Non vedo l'ora di eventuali suggerimenti.

+0

tessuto + boto appare davvero come una buona combinazione per questo compito. Può valere la pena parallelizzare l'attività su ogni istanza (a meno che non ci si aspetti di avere 1200 istanze, una per file), magari usando un 'Pool' dal modulo' multiprocessing'. Inoltre, il modo in cui analizzi il file e modifichi i risultati avrà probabilmente un impatto notevole sul tempo totale. Hai esaminato il 'numpy'? – goncalopp

+1

Quindi nessuno cerca di ripetere i possibili suggerimenti - potresti descrivere quello che hai fatto nel tuo script esistente che è troppo lento - quindi sappiamo di non seguire questa strada :) –

+0

@ JonClements - sembra una richiesta giusta. Bascamente, ho provato due approcci. Ho provato a mettere i dati in uno schema temporaneo e indicizzarlo (se necessario) ed eseguire query su di esso per "massaggiare" i dati e inserirli nel formato richiesto. Era troppo lento perché credo che gli indici fossero molto più grandi della cache di PostgreSQL. Nota: ho una piccola istanza di PostgreSQL in esecuzione su Heroku. (continuerà nel prossimo commento) –

risposta

2

Uso spesso una combinazione di SQS/S3/EC2 per questo tipo di lavoro batch. Metti in coda i messaggi in SQS per tutto il lavoro che deve essere eseguito (suddiviso in blocchi ragionevolmente piccoli). Spin up N istanze EC2 che sono configurate per iniziare a leggere i messaggi da SQS, eseguire il lavoro e inserire i risultati in S3, quindi, e solo successivamente, eliminare il messaggio da SQS.

È possibile ridimensionarlo a livelli impazziti e ha sempre funzionato molto bene per me. Nel tuo caso, non so se memorizzi i risultati in S3 o vai direttamente a PostgreSQL.

+0

Solo per curiosità, come otterresti i tuoi copioni nell'istanza EC2? Li vorresti prendere da un repo git? O semplicemente scp il copione (s) oltre? –

+0

Ho usato un certo numero di tecniche. Potresti scrivere script basati su Paramiko per scpare i file. È possibile utilizzare cloud-init e estrarre gli script da S3. Potresti usare Fabric. Potresti usare i modelli CloudFormation. Ci sono molte scelte – garnaat

+0

Grazie per la risposta. Si; sembra un sacco di opzioni. Come ho menzionato nella mia domanda iniziale, mi sto orientando verso l'uso di Fabric, ma mi chiedevo cosa hai fatto qui. –

2

ho fatto qualcosa di simile qualche tempo fa, e la mia messa a punto era come

  • un'istanza multicore (x-large o più), che converte i file di origine prima (XML/CSV) in un formato intermedio . È possibile eseguire copie (num-of-core) dello script di conversione su di esso in parallelo. Poiché il mio obiettivo era mongo, ho usato json come formato intermedio, nel tuo caso sarà sql.

  • a questa istanza sono associati N volumi. Una volta che un volume si riempie, viene staccato e collegato alla seconda istanza (tramite boto).

  • la seconda istanza esegue un server DBMS e uno script che importa i dati preparati (sql) nel db. Non so nulla di postgres, ma suppongo che abbia uno strumento come mysql o mongoimport. Se sì, usalo per creare inserimenti di massa invece di fare query tramite uno script python.

3

Avete eseguito alcune misurazioni delle prestazioni: dove sono i colli di bottiglia? È legato alla CPU, vincolato all'IO, legato al DB?

Quando è collegato alla CPU, è possibile provare un python JIT come pypy.

Quando è vincolato all'IO, sono necessari più HD (e alcuni striping md su di essi).

Quando è collegato al database, è possibile provare a eliminare prima tutti gli indici e i tasti.

La scorsa settimana ho importato il DB di Openstreetmap in un'istanza di Postgres sul mio server. I dati di input erano circa 450G. La pre-elaborazione (che è stata eseguita qui in JAVA) ha appena creato i file di dati grezzi che potevano essere importati con il comando 'copia' di Postgres. Dopo l'importazione sono state generate le chiavi e gli indici.

L'importazione di tutti i dati grezzi ha richiesto circa un giorno, quindi sono stati necessari diversi giorni per creare chiavi e indici.

1

Potresti trarre vantaggio da hadoop sotto forma di Amazon Elastic Map Reduce. Senza entrare troppo in profondità, può essere visto come un modo per applicare una certa logica ai massicci volumi di dati in Parralel (fase Mappa).
C'è anche la tecnologia hadoop chiamata hadoop streaming - che consente di usare script/eseguibili in qualsiasi lingua (come python).
Un'altra tecnologia hadoop che puoi trovare utile è sqoop - che sposta i dati tra HDFS e RDBMS.

+0

Grazie per la risposta. DEEEEEP giù dentro di me, so che Hadoop ed Elastic MapReduce sono la cosa giusta da usare qui. Tuttavia, non riesco a capire come funziona con quello che sto cercando di realizzare. Parte del mio problema è che praticamente ogni esempio che abbia mai visto è lo stesso sciocco problema di conteggio delle parole. Il mio è più un problema ETL (estrai, trasforma, carica). Posso facilmente immaginare la funzione Map che gestisce la maggior parte delle trasformazioni. Ma le trasformazioni dipendono dal cliente. Quindi, non è un calcolo semplice (es. (X * y)/2). –

1

È inoltre possibile utilizzare il calcolo parallelo ipython s' molto facilmente su EC2 con StarCluster
StarCluster è un programma di utilità per la creazione e la gestione di cluster di calcolo distribuito ospitati su EC2 di Amazon.

http://ipython.org/ipython-doc/stable/parallel/parallel_demos.html
http://star.mit.edu/cluster/docs/0.93.3/index.html
http://star.mit.edu/cluster/docs/0.93.3/plugins/ipython.html

+0

Grazie per il post! Non ne ho mai nemmeno sentito parlare! Lo guarderò! Grazie ancora! –