Laravel 里面的 chunk 分块效率问题
laravel里面的chunk分块效率问题
在批处理较大数据数据时,laravel提供了chunk处理大块数据的方法,但数据量大了之后效率会非常慢
本次数据库测试数据供有二十万零一千(201000)条数据
chunk方法
<?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数据用了两分多钟,效率似乎有点低,解决方法
记录最大id方法:
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 协议》,转载必须注明作者和本文链接
推荐文章: