1 回答

TA贡献1836条经验 获得超4个赞
问题可能不是gzip文件本身,当然你可以下载它,然后处理它,这会保留同样的问题。
因为您正在将所有产品加载到单个数组(内存)中
$importedProducts[] = $product;
您可以注释掉这一行,并查看它是否达到了您的内存限制。
通常我会创建一个像 addProduct($product) 这样的方法来处理内存安全。
然后,您可以在进行批量插入之前从那里决定最大产品数量。为了达到最佳速度..我通常使用 1000 到 5000 行之间的东西。
例如
class ProductBatchInserter
{
private $maxRecords = 1000;
private $records = [];
function addProduct($record) {
$this->records[] = $record;
if (count($this->records) >= $this->maxRecords) {
EloquentModel::insert($this->records);
$this->records = [];
}
}
}
然而,我通常不会将其实现为单个类,但在我的项目中,我习惯将它们集成为可用于任何雄辩模型的 BulkInsertable 特征。
但这应该给你一个方向,告诉你如何避免内存限制。
或者,更简单,但速度明显慢,只需插入现在将其分配给数组的行。但这会给你的数据库带来巨大的负载,而且速度会非常慢。
如果 GZIP 流是瓶颈
正如我所期望的,这不是问题,但如果是的话,那么你可以使用 gzopen()
https://www.php.net/manual/en/function.gzopen.php
并将 gzopen 句柄嵌套为 fgetcsv 的句柄。
但我希望您正在使用的流处理程序已经以相同的方式为您执行此操作。
如果不是,我的意思是这样的:
$input = gzopen('input.csv.gz', 'r');
while (($row = fgetcsv($input)) !== false) {
// do something memory safe, like suggested above
}
如果您无论如何都需要下载它,有很多方法可以做到这一点,但请确保您使用内存安全的东西,例如 fopen / fgets 或 guzzle 流,并且不要尝试使用像 file_get_contents() 这样的东西将其加载到内存中
- 1 回答
- 0 关注
- 104 浏览
添加回答
举报