Ho creato uno script in Laravel che legge un file JSON riga per riga e importa il contenuto nel mio database.Come evitare l'esaurimento della memoria quando si inserisce un milione di righe in mysql con php
Tuttavia, durante l'esecuzione dello script, viene visualizzato un errore di memoria insufficiente dopo l'inserimento di circa 80.000 di record.
mmap() failed: [12] Cannot allocate memory
mmap() failed: [12] Cannot allocate memory
PHP Fatal error: Out of memory (allocated 421527552) (tried to allocate 12288 bytes) in /home/vagrant/Code/sandbox/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php on line 1758
mmap() failed: [12] Cannot allocate memory
PHP Fatal error: Out of memory (allocated 421527552) (tried to allocate 32768 bytes) in /home/vagrant/Code/sandbox/vendor/symfony/debug/Exception/FatalErrorException.php on line 1
ho costruito una sorta di coda di fortuna ai soli commettere gli elementi raccolti ogni 100, ma questo fatto alcuna differenza.
Questo è ciò che la parte del mio codice che fa gli inserti assomiglia:
public function callback($json) {
if($json) {
$this->queue[] = [
'type' => serialize($json['type']),
'properties' => serialize($json['properties']),
'geometry' => serialize($json['geometry'])
];
if (count($this->queue) == $this->queueLength) {
DB::table('features')->insert($this->queue);
$this->queue = [];
}
}
}
E 'gli inserti effettivi (DB::table('features')->insert($this->queue);
) che stanno causando l'errore, se lascio quelli fuori posso perfettamente iterare su tutto linee e li echeggia senza problemi di prestazioni.
Immagino di poter allocare più memoria, ma dubito che questa sarebbe una soluzione perché sto cercando di inserire 3 milioni di record e al momento è già in corso dopo 80 K con 512 MB di memoria allocata. Inoltre, in realtà voglio eseguire questo script su un server a basso budget.
Il tempo necessario per l'esecuzione di questo script non è di alcuna preoccupazione, quindi se potessi in qualche modo rallentare l'inserimento di record in basso sarebbe una soluzione per la quale potrei accontentarmi.
vincolato a overhead di laravel, quindi smetterei di usarlo per primo. –
L'ultima volta che dovevo farlo, ho scritto uno script cron che girava ogni N ore e prendeva N records, aggiornando i record processati con una bandiera. Ogni tanto lo script falliva, ma si riavviava semplicemente selezionando i record non elaborati. Non è la soluzione migliore (misurando la possibile sovrapposizione, per esempio, sperando che qualcuno qui faccia luce su di essa.) Modifica: Dagon ha anche un punto, aumenterà significativamente la perfomance se la costruirai su misura .. –
Potresti passare in un imposta il limite di N righe al tuo metodo callback() di qualsiasi importo tu * puoi * elaborare contemporaneamente.Alla fine del tuo metodo, reindirizza alla tua pagina con un aumento di N righe + N per elaborare il batch successivo nella tua coda ? – Landjea