sono un felice utilizzatore di codeigniter, ma che sta valutando di passare a yii2 per l’implementazione dei nuovi progetti.
In Codeigniter ero abituato ad usare un paio di funzioni utili: gli inserimenti e modifiche batch.
Queste due funzioni erano davvero comode quando avevo a che fare con grandi quantità di dati.
Ora mi trovo a leggere da un file circa 20.000 righe, le quali devono essere inserite nel database oppure semplicemente aggiornate.
Il problema che mi si pone con yii2 è: il tempo impiegato è davvero lungo ed i 128MB di ram assegnati al processo PHP purtroppo non bastano per eseguire l’intero comando.
Vi allego un esempio di codice che sto usando per l’aggiornamento:
Per fare grossi import ti conviene separare l’import in blocchi di N righe e non in un’unica transazione altrimenti, con un foreach di tutto, php si deve mettere in memoria tutte le 20k righe e ovviamente l’uso delle risorse diventa elevato.
Puoi provare diverse vie, una è caricare il file nel server e importarle con il comando mysql "LOAD DATA LOCAL INFILE", questo può essere buono se esegui il comando via CLI e non da una pagina web.
La seconda soluzione è un po’ più complicata e, per evitare che php vada in timeout, dovresti ricaricare la pagina passando ogni volta il punto in cui sei arrivato.
Esempio, decidi che N è il tuo numero di righe da importare ad ogni ciclo.
carichi il file e leggi il numero totale delle righe (così sai ogni volta a che punto stai), carichi le prime N righe in memoria e fai l’import, poi fai un refresh della pagina passando il numero di righe che hai importato (sarà il tuo offset), al caricamento importi le righe da offset a offset + N e così via…
E’ la via più complicata ma ti permette di importare un numero infinito di righe perché ad ogni ciclo l’uso delle risorse è limitato al valore di N
Per eseperienza personale, dovendo lavorare anche con milioni di record talvolta, i batch li eseguo avviando la transaction come fai te, ma poi eseguo del SQL puro contro il db, questo ha due benefici
risparmia tantissima memoria perchè PHP non deve manovrave migliaia di volte con gli oggetti di yii
risparmia tantissimissimo tempo, per lo stesso motivo
Se non splittate vi consiglio "LOAD DATA INFILE" su MySQL che è molto più veloce di una insert, circa 20 volte più veloco secondo oracle ed è buona cosa, sempre per le prestazioni, disabilitare il controllo delle chiavi straniere quando si importa.