Вот консольная команда, которую я написал в Laravel, и мне было интересно, как я могу сделать ее лучше и быстрее? Что я сделал не так?
И если вы можете представить мне книгу, чтобы я мог лучше разбираться в алгоритмах и писать лучший код, я был бы признателен.
Спасибо
$process = Process::create([
'started_at' => now()
]);
//set how many subscription to get from db in each iteration
//we use this for loop to prevent memory exhaustion
$subscriptionsCountPerIteration = 1000;
$subscriptionsCount = Subscription::count();
$numberOfIterations = $subscriptionsCount/$subscriptionsCountPerIteration;
for($i=0; $i < $numberOfIterations; $i++){
$subscriptions = Subscription::query()->limit($subscriptionsCountPerIteration)->offset($subscriptionsCountPerIteration * $i)->get();
foreach($subscriptions as $subscription){
$subscription->updateStatus($process);
}
}
$process->finished_at = now();
$process->save();
Я думаю, что то, что у меня есть две петли, - плохая идея.
Покажите свой метод updateStatus
Я считаю, что один вложенный цикл в этом случае неизбежен, потому что иначе обновление не может быть выполнено в пакетном режиме. Однако у Laravel есть собственный функционал для этого, о котором можно прочитать здесь. Я предлагаю вам проверить, использовать ли chunk()
или chunkById()
, потому что эти две функции обрабатывают пакет по-разному.
Вы можете «оптимизировать» скорость выполнения команды, запустив логику updateStatus()
внутри задания . Это означает, что команда будет асинхронно отправлять новое задание для проверки состояния и быстро возвращаться, поскольку фактическая логика выполняется в рабочей очереди.
Это будет выглядеть примерно так:
foreach($subscriptions as $subscription){
CheckSubscriptionStatusJob::dispatch($subscription->id);
}
Примечание. Фактическая проверка статусов по-прежнему будет занимать столько же времени, но команде не нужно будет ждать завершения проверки. Кроме того, вы можете использовать несколько очередей для параллельного выполнения нескольких заданий.
Вложенные циклы выглядят так, как будто они нужны только для того, чтобы разбить большой процесс на сегменты. Циклы — это плохо, когда вы постоянно просматриваете одни и те же данные, чего здесь нет (AFAIK).