2015-01-22 2 views
7

Ich ziehe 100k Datensätze aus temporären Tabellen, mache ein paar kleine Änderungen an den Daten, lade Fotos herunter und lege dann die Felder, die ich behalten muss, in eine "Master" -Tabelle. Dies führt schnell dazu, dass meine App abstürzt, da der Arbeitsspeicher knapp wird.Wie verwende ich Laravel's Chunk, um zu vermeiden, dass der Arbeitsspeicher knapp wird?

Ich lese die sehr kurze Dokumentation über die Verwendung von Chunk() mit Laravel eloquenten ORM, aber ich weiß nicht, wie man es überhaupt in meiner Klasse zu implementieren beginnt. Hier

ist, was ich derzeit tue:

public function fire() 
{ 
    // Turn off query logging 
    DB::connection()->disableQueryLog(); 

    $feeds = RetsFeed::where('active','=',1)->get(); 
    foreach ($feeds as $feed) 
    { 

     $class = "TempListing{$feed->board}"; 

     $listings = $class::orderBy('MatrixModifiedDT','desc')->get(); 

     $listings->each(function($listing) use ($feed) { 
      ListingMigrator::migrateListing($listing,$feed); 
      echo "Feed: $feed->board\r\n"; 
      echo "SubcondoName: $listing->SubCondoName\r\n"; 
      echo "Development: $listing->Development\r\n"; 
      echo "\r\n"; 
     }); 
    } 

} 

Jedes Futter (oder Datenquelle) in eine temporäre Tabelle in einer anderen lästige Pflicht abgeladen wird. Das funktioniert gut. Dann greife ich alle Listen aus einer Tabelle (die durchschnittlich 30k ist) und führe meine ListingMigrator-Methode aus.

Wo gebe ich den Chunk in diesem Beispiel ein? Wäre es die Zeile:

$listings = $class::orderBy('MatrixModifiedDT','desc')->get(); 

verstehe ich nicht vollständig die Schließung in dem beredten docs. Das ist alles, was sie dazu zu sagen haben, und hier ist das Codebeispiel aus der Laravel Website:

User::chunk(200, function($users) 
{ 
    foreach ($users as $user) 
    { 
     // 
    } 
}); 

Antwort

14

Der chunk Aufruf den get Anruf ersetzen sollte - es ausgelegt ist, auf dem Pre-get() Query Builder-Objekt zu arbeiten .

$listings = $class::orderBy('MatrixModifiedDT','desc'); 

$listings->chunk(200, function($listings) use($feed) { 
    $listings->each(function($listing) use ($feed) { 
     ListingMigrator::migrateListing($listing,$feed); 
     echo "Feed: $feed->board\r\n"; 
     echo "SubcondoName: $listing->SubCondoName\r\n"; 
     echo "Development: $listing->Development\r\n"; 
     echo "\r\n"; 
    }); 
}); 
+1

Dies scheint wie ein Charme zu arbeiten! Vielen Dank für Ihre Großzügigkeit bei der Beantwortung. Meine eine Frage ist jedoch, wie wir die 200-Nummer für den Brocken bestimmen. Mein Verständnis ist, dass es so viele verarbeitet und dann im Grunde "neu beginnt", weil es kein besseres Wort gibt. Wäre es nicht sicher, diese Zahl wirklich niedrig zu halten, wie etwa 10? Sind die einzigen Kosten dafür die zusätzlichen Datenbankaufrufe? –

+2

@ChrisFarrugia Chunk-Größe ist ziemlich willkürlich und die einzige harte Voraussetzung ist, dass es eine ausreichend kleine Nummer ist, so dass Sie nicht aus RAM in einem einzigen Stück ausgehen. Wenn Ihre Datenbank die Belastung nicht stört, sind 10 Stück gut. Stücke von 200 sind wahrscheinlich auch in Ordnung. – ceejayoz

+2

Hinweis: Wenn der "Chunk" das Ändern von Datensätzen umfasst, die sich auf die Abfrage auswirken können, z. B. Löschen, Löschen, Spaltenwechsel in der Abfrage usw., müssen Sie den Chunk mit einer while-Anweisung umgeben. Siehe http://StackOverflow.com/questions/32700537/eloquent-chunk-missing-half-the-results und möglicherweise http://laravel.io/forum/09-22-2015-chunk-missing-half-the -results? page = 1 – brianlmerritt

Verwandte Themen