2014-12-01 18 views
6

Come mantenere grandi quantità di dati leggendo da un file CSV (diciamo 20 milioni di righe). Questo è in corso da circa 1 1/2 giorni finora e ha persistito solo 10 milioni di righe, come posso eseguire il batch di questo in modo che diventi più veloce e ci sia la possibilità di eseguirlo in modo parallelo.Come mantenere grandi quantità di dati leggendo da un file CSV

Sto usando il codice qui per leggere il CSV, vorrei sapere se c'è un modo migliore per raggiungere questo obiettivo.

consultare: dealing with large CSV files (20G) in ruby

+0

Qual è l'obiettivo di avere 20mil righe in memoria? Perché non basta leggere ogni riga e trasferirla in un database SQLite?(poi fai l'analisi lì) Se stai cercando di far funzionare una grande quantità di dati, allora vorrai dare un'occhiata a MapReduce. – Besto

+0

Vorrei elaborare tutti i dati e archiviarli nel database MySQL per ulteriori elaborazioni. Fammi sapere se riesco a ottimizzare il modo in cui leggo i dati o il batch persiste nei dati. Apprezzare qualsiasi frammento di codice qui. Anche le file sono passate? – brisk

+0

Puoi fornire uno schema di esempio? Metterò insieme un frammento. – Besto

risposta

4

Si può provare a dividere prima il file in diversi file più piccoli, allora si sarà in grado di elaborare più file in parallelo.

Probabilmente per splintaggio il file sarà più veloce per utente uno strumento come scissione

split -l 1000000 ./test.txt ./out-files- 

Poi mentre si stanno elaborando ciascuno dei file e supponendo che si sta inserendo record invece di inserire uno per uno, voi può combinarli in lotti e fare inserimenti di massa. Qualcosa di simile:

INSERT INTO some_table 
VALUES 
(1,'data1'), 
(2, 'data2') 

Per migliorare le prestazioni è necessario creare l'istruzione SQL da soli ed eseguirlo:

ActiveRecord::Base.connection.execute('INSERT INTO <whatever you have built>') 
+2

Inoltre, assicurati di eseguire tutti i tuoi inserimenti all'interno di un blocco 'ActiveRecord :: Base.transaction {}'. –

2

Dal momento che si desidera a persistere i dati di MySQL per l'ulteriore elaborazione, utilizzando Load I dati in Infile da MySQL sarebbero più veloci. qualcosa di simile al seguente con il vostro schema:

sql = " 'big_data.csv' LOAD DATA LOCAL INFILE INTO test TABELLA CAMPI denuncia da parte di '' CHIUSA DA '\"' righe che terminano con '\ n' (foo, foo1)"

con = ActiveRecord :: Base.connection

Con.Execute (SQL)

+0

aggiungi local_infile: true a database.yml come per [collegamento] (http://stackoverflow.com/questions/21256641/enabling-local-infile-for-loading-data-into-remote-mysql-from-rails) – Graham

1

punti chiave:

  1. Se si utilizza il motore MySQL InnoDB, il mio consiglio è che sempre definire un incremento automatico PRIMARY KEY, InnoDB utilizza indice cluster per memorizzare i dati nella tabella. Un indice cluster determina l'ordine fisico dei dati in una tabella.
    riferiscono: http://www.ovaistariq.net/521/understanding-innodb-clustered-indexes/
  2. Config tuoi parametri di MySQL Server, i più importanti sono
    (1) chiudi mysql binlog
    (2) innodb_buffer_pool_size.
    (3) innodb_flush_log_at_trx_commit
    (4) bulk_insert_buffer_size
    Si può leggere questo: http://www.percona.com/blog/2013/09/20/innodb-performance-optimization-basics-updated/
  3. Si dovrebbe usare produttore-consumatore scenario.

Ci scusiamo per il mio inglese scarso.

Problemi correlati