laravel裡面的chunk分塊效率問題
在批處理較大資料資料時,laravel提供了chunk處理大塊資料的方法,但資料量大了之後效率會非常慢
本次資料庫測試資料供有二十萬零一千(201000)條資料
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Test as TestModel;
class Test extends Command
{
protected $signature = 'db:test';
/**
* 處理時間
* @return float\
*/
public function microtime_float():float\
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
public function chunkTest()
{
// 每次處理
$speed = 1000;
// 進度條
$bar = $this->output->createProgressBar(TestModel::query()->count());
// 記錄開始時間
$timeStart = $this->microtime_float();
// chunk 分塊處理資料
TestModel::query()->chunk($speed, function ($item) use ($bar, $speed) {
// 業務處理邏輯...
// ....
// 進度條步進{$speed}步
$bar->advance($speed);
});
$bar->finish();
// 處理完成,記錄結束時間
$timeEnd = $this->microtime_float();
$time = $timeEnd - $timeStart;
// 輸出資訊
$this->info('chunk用時:'. $time);
}
}
執行:
php artisan db:test
201000/201000 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% chunk用時:138.11135005951
發現出了20w資料用了兩分多鐘,效率似乎有點低,解決方法
public function idTest()
{
// 進度條
$bar = $this->output->createProgressBar(TestModel::query()->count());
$timeStart = $this->microtime_float();
// 記錄最大的id
$maxId = 0;
// 每次處理多少條資料
$speed = 1000;
while (true) {
$models = TestModel::query()
// 每次迴圈加上id條件
->where('id', '>', $maxId)
->limit($speed)
->orderBy('id')
->get();
// 處理具體業務邏輯...
// 如果沒有資料就代表處理完成,break;
if ($models->isEmpty()) {
break;
}
// 記錄下本次的最大id,下次迴圈時當作條件
$maxId = $models->max(['id']);
$bar->advance($speed);
}
$timeEnd = $this->microtime_float();
$time = $timeEnd - $timeStart;
$bar->finish();
$this->info('id條件用時: '. $time);
}
執行:
php artisan db:test
201000/201000 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%id條件用時: 7.790333032608
20W資料只用了7秒
本作品採用《CC 協議》,轉載必須註明作者和本文連結