在Laravel种如何处理大CSV文件解决方案
Laravel  /  管理员 发布于 8个月前   191
在商业世界中,处理庞大的 CSV 文件是家常便饭,尤其是当你有大量数据需要分析、报告或移动时。
如果你正在使用 Laravel 并需要处理大型 CSV 文件,那你就来对地方了。
我们将指导你以最顺畅的方式处理这项任务,而不会对你的应用程序性能造成影响。
内存和性能
首先,让我们来谈谈房间里的大象:内存和性能。
处理庞大的 CSV 会占用大量内存,并可能降低应用程序的运行速度。
当然,你可能会考虑提高内存限制或延长超时时间。
但老实说,这就像在漏水的管道上贴创可贴,并不是最佳解决方案。
进入 Spatie 的 Simple Excel
我们将使用一款名为 Simple Excel by Spatie 的软件包来代替创可贴。
如果你在点头,因为你期望 Spatie 能提供解决方案,那你并不孤单。
composer require spatie/simple-excel
假设您已经准备好 CSV 文件,我们将使用 SimpleExcelReader 加载它。
最酷的是,默认情况下,它会返回一个 LazyCollection -
将其视为处理数据的一种更周到的方式,而不会耗尽服务器的内存。
这意味着您可以一点一点地处理文件,使您的应用程序保持轻便。
$rows is an instance of Illuminate\Support\LazyCollection
使用Laravel Job 来处理CSV
现在,在我们开始编写代码之前,让我们先设置一个 Laravel Job 来管理 CSV 处理。
php artisan make:job ImportCsv
这就是我们的 ImportCsv 作业:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\SimpleExcel\SimpleExcelReader;
class ImportCsv implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
SimpleExcelReader::create(storage_path('app/public/products.csv'))
->useDelimiter(',')
->useHeaders(['ID', 'title', 'description'])
->getRows()
->chunk(5000)
->each(
// Here we have a chunk of 5000 products
);
}
}
游戏计划如下:
给 CSV 分块:
我们要把文件分成易于管理的小块,这样就有了一个 LazyCollection 供我们使用。
作业分派:
对于每个分块,我们都要发送一个作业。这样,我们就能分批处理,对服务器来说也更方便。
插入数据库:
然后将每个数据块插入数据库,操作简单方便。
对 CSV 进行分块
LazyCollection 准备就绪后,我们将 CSV 分割成块。
把它想象成把一个巨大的三明治切成一小块一小块,这样处理起来就容易多了。
php artisan make:job ImportProductChunk
对于 CSV 中的每一部分,我们都将创建并启动一个作业。
这些作业就像勤劳的工人,每个作业都会获取一个数据块,并小心翼翼地将数据插入到数据库中。
<?php
namespace App\Jobs;
use App\Models\Product;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class ImportProductChunk implements ShouldBeUnique, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $uniqueFor = 3600;
/**
* Create a new job instance.
*/
public function __construct(
public $chunk
) {
//
}
/**
* Execute the job.
*/
public function handle(): void
{
$this->chunk->each(function (array $row) {
Model::withoutTimestamps(fn () => Product::updateOrCreate([
'product_id' => $row['ID'],
'title' => $row['title'],
'description' => $row['description'],
]));
});
}
public function uniqueId(): string
{
return Str::uuid()->toString();
}
}
确保唯一性
在工作中使用 $uniqueFor 和 uniqueId 是需要牢记的重要事项。
这就好比给每个工人一个唯一的身份徽章,这样就不会意外地让两个人做同样的工作--这是提高效率的大忌。
调度工作
回到我们的 ImportCsv 作业中,我们将为 each 方法中的每个块调度一个作业。
这就像在说:"你得到一大块,你也得到一大块,每个人都得到一大块!"
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\SimpleExcel\SimpleExcelReader;
class ImportCsv implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public function __construct()
{
//
}
/**
* Execute the job.
*/
public function handle(): void
{
SimpleExcelReader::create(storage_path('app/public/products.csv'))
->useDelimiter(',')
->useHeaders(['ID', 'title', 'description'])
->getRows()
->chunk(5000)
->each(
fn ($chunk) => ImportProductChunk::dispatch($chunk)
);
}
}
就这样!您的数据块可以独立处理,不会占用任何内存。
如果你赶时间,只需添加更多的 Worker,你的数据就会像运转良好的机器一样,得到更快的处理。
在 Laravel 中处理大型 CSV 文件并不令人头疼。
有了正确的工具和方法,你就能在处理所有数据的同时保持应用程序的平稳运行。
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号