3 risposte

★ Miglior risposta

Ho problemi così con i database enormi e la colpa è quasi sempre la stessa: stai caricando l'intero file in memoria prima di elaborarlo! Un CSV di 500MB diventa assolutamente mostruoso quando parsato in array, e aumentare l'heap è solo mettere un cerotto su una ferita. La soluzione vera è usare gli stream - elabori riga per riga mentre scrivi i dati in un database o file, e Node.js neanche avrà bisogno di tenere in memoria più di pochi KB alla volta! Prova con la libreria `csv-parser` con stream o anche scrivere un parser personalizzato con `fs.createReadStream()` e gli eventi, che questo ti cambia completamente il gioco.

Ho avuto un'esperienza simile quando cercavo di processare file grandi tutto in una volta e mi sono resa conto che il problema non era solo la memoria - era il fatto di caricare tutto insieme nella RAM. Con un CSV di 500MB, se provi a leggere l'intero file e poi elaborarlo, ti rimani senza memoria in fretta. La soluzione è usare gli stream invece di caricare tutto in memoria. In Node.js hai il modulo `fs.createReadStream()` che ti permette di leggere il file a pezzetti. Se stai usando librerie tipo `csv-parser`, riesci a concatenare gli stream per elaborare riga per riga senza sovraccaricare la RAM.

Un'altra cosa che è cambiata per me è stata capire che anche con gli stream, se la tua logica di elaborazione è lenta (tipo operazioni sincrone nel loop, query al database senza batch), crei un collo di bottiglia. Quando lo stream fornisce dati più velocemente di quanto tu riesca a elaborare, la memoria si accumula comunque. Usa `pause()` e `resume()` per controllare il flusso, oppure implementa il back-pressure correttamente. Se stai facendo query al database per ogni riga, raggruppale in batch - tipo, raggruppa 1000 righe e fai un'operazione sola invece di 1000 separate.

Più o meno quale operazione stai facendo con i dati del CSV? E stai salvando i risultati da qualche parte (file, database) oppure solo elaborando e restituendo tramite API? La risposta aiuta perché il problema potrebbe essere anche nel modo in cui stai inviando la risposta al client.

gabriel_oliveira asker Sto elaborando i dati e salvandoli direttamente nel database, senza batch. Proverò con gli stream e raggrupperò le query in lotti da 1000, grazie!

Il problema probabilmente non è solo aumentare l'heap, no. Quando carichi un file di 500MB intero in memoria prima di elaborarlo, Node.js rimane soffocato anche così. La gente ha ragione a sottolinearlo, ma c'è un dettaglio che nessuno ha menzionato: se stai usando librerie come `csv-parser` o simili senza configurare gli stream nel modo giusto, potrebbero fare il buffer di varie righe prima di elaborarle, il che peggiora tutto. Devi usare gli stream davvero - `fs.createReadStream()` + un parser che rispetti chunk piccoli. In questo modo Node.js elabora riga per riga (o in piccoli lotti) senza far saltare la memoria.

Un'altra cosa che fa danni: se stai facendo query al database dentro il loop di elaborazione del CSV, ogni riga potrebbe generare una query separata. Immagina 500 mila righe = 500 mila query. Il database va in panico, la coda cresce, la memoria esplode. Fallo in batch - elabora 1000 righe alla volta, fai un insert in lotto, poi passa al prossimo. Con stream + batching riusci a elaborare file molto più grandi senza bloccarsi.

La tua risposta

Accediper rispondere.