Nell’ articolo Laravel: importare files con Laravel Excel abbiamo visto un utilizzo basilare della libreria Laravel Excel. La lettura del file csv avviene con un caricamento unico in memoria con un impatto negativo in termini di prestazioni e tempi di caricamento.
Avrete potuto notare che il caricamento del file Prova-2.csv di 22 mila righe richiede svariate decine di secondi. Come riferimento, nella configurazione di prova (server virtuale con scarse risorse) sono occorsi circa 48 secondi per completare il caricamento.
Vediamo come possiamo migliorare le prestazioni
1 – Utilizzo di chunk
Per limitare l’utilizzo della memoria, Laravel Excel mette a disposizione il costrutto WithChunkReading. Questo leggerà il foglio di calcolo a blocchi, mantenendo sotto controllo l’uso della memoria.
Riprendiamo quanto creato nel progetto precedente e modifichiamo il file app/Imports/CsvDataImport.php
<?php
namespace App\Imports;
use App\Models\CsvData;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class CsvDataImport implements ToModel, WithHeadingRow, WithChunkReading
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new CsvData([
'colonna1' => $row['colonna1'],
'colonna2' => $row['colonna2'],
]);
}
public function chunkSize(): int
{
return 5000;
}
}
Se impostiamo chunkSize() a 1000 il tempo di caricamento scende da circa 49 a 39 secondi (-20% tempo di attesa) e a 5000 scendiamo a 34 secondi (-31% rispetto al tempo di attesa iniziale). Se continuiamo a modificare il chunkSize vedremo che i tempi non si ridurranno in modo sostanziale. Vediamo come fare a efficientare ulteriormente il caricamento
2 – Utilizzo di chunk e inserimento batch
Per migliorare ulteriormente le prestazioni combiniamo inserimenti batch ai chunk:
<?php
namespace App\Imports;
use App\Models\CsvData;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
class CsvDataImport implements ToModel, WithHeadingRow, WithBatchInserts, WithChunkReading
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new CsvData([
'colonna1' => $row['colonna1'],
'colonna2' => $row['colonna2'],
]);
}
public function batchSize(): int
{
return 5000;
}
public function chunkSize(): int
{
return 5000;
}
}
In questo modo il tempo di caricamento scende drasticamente, a circa 4 secondi in totale!
Qui trovi il codice aggiornato https://github.com/SviluppoK/laravel-csv-upload-1/tree/release/v2.0




Lascia un commento