Es ist besser, chunkById anstelle von chunk zu verwenden, um fehlende Zeilen bei Batch-Updates zu vermeiden. Die Verwendung von Chunk kann den Offset nachfolgender Abfragen nach dem Aktualisieren von Zeilen verschieben, was dazu führt, dass unverarbeitete Zeilen übersprungen werden.
Zum Beispiel:
Post::where('processed', 0)->chunk(100, function($posts) { foreach($posts as $post) { $post->processed = 1; $post->save(); } });
Der obige Code generiert die folgenden Abfragen.
select * from `posts` where `processed` = 0 limit 100 offset 0 select * from `posts` where `processed` = 0 limit 100 offset 100 ...
Der erste Block aktualisiert 100 Zeilen. Die zweite Abfrage überspringt, ohne sich dessen bewusst zu sein, 100 unverarbeitete Zeilen, da sie immer noch den Offset verwendet.
Das Obige wird ausführlich erklärt von
Thai Nguyen Hung
Wenn wir versuchen, eine begrenzte Anzahl von Zeilen mit der chunk()-Methode von Laravel zu verarbeiten, können wir davon ausgehen, dass der folgende Code nur 5 Benutzer in Stapeln von 2 verarbeitet:
$query = \App\Models\User::query()->take(5); $query->chunk(2, function ($users) { // Process users });
Dadurch werden jedoch alle Benutzer in der Datenbank verarbeitet, jeweils zwei gleichzeitig. Dies geschieht, weil die chunk()-Methode von Laravel das auf die Abfrage angewendete take()-Limit ignoriert, was dazu führt, dass alle Zeilen in Blöcken verarbeitet werden.
Um sicherzustellen, dass nur eine begrenzte Anzahl von Zeilen (z. B. 5 Benutzer) in Blöcken verarbeitet werden, können wir einen benutzerdefinierten Indexzähler implementieren, der die Chunking-Schleife unterbricht, nachdem das angegebene Limit erreicht wurde. Der folgende Code erreicht dies:
class UserProcessor { private int $index = 0; private int $limit = 5; public function process() { $query = \App\Models\User::query(); $query->chunk(2, function ($users) { foreach ($users as $user) { $this->index++; // Process each user here // Example: $user->processData(); if ($this->index >= $this->limit) { // Stop processing after reaching the limit return false; // This will stop chunking } } }); } }
Hinweis
$index und $limit sind Eigenschaften der Klasse, keine Methodenvariablen, die mit use($index, $limit) an den Abschluss übergeben werden. Dies liegt daran, dass über use() übergebene Variablen nach Wert in das Abschlussobjekt kopiert werden. Daher wirken sich alle Änderungen innerhalb des Abschlusses nicht auf die ursprünglichen Werte aus, weshalb es sich um Klasseneigenschaften handeln muss, um Änderungen über Iterationen hinweg ordnungsgemäß zu aktualisieren und zu verfolgen.
Das obige ist der detaillierte Inhalt vonOptimierung von Laravel-Abfragen: Der richtige Weg, Daten aufzuteilen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!