Php 解析和处理大型文件
我有一个大的CSV文件,我需要分为4部分,然后发送数据到数据库;我遇到的问题是CSV文件可能是1GB+(一次可能不止一个),这会造成各种时间延迟和内存问题 我想得到一些关于如何改进和加快流程的帮助 我正在测试的文件有45000条记录~10mb文件 现在我正在将文件加载到数组中,数组使用的大小大约是文件大小的3倍,所以对于10mb文件,我们说的是30mb内存;我希望通过逐行读取文件来减少对30mb内存的需求,但现在来看一下这个 处理部分相当简单,基本上我循环处理数据数组 最后一部分是将数据保存到数据库,目前的主要问题在于,将数据保存到数据库需要花费时间 起初,我尝试创建一个大字符串并将其全部发送到DB中,但22k记录需要大约2GB的ram内存;即使这个过程很快,我的内存还是会一直不足 我目前实现的方法是一次添加行,这不需要太多内存,但处理45k条记录可能需要将近一个小时 我的下一步是创建一个包含完整查询列表的mysql文件,并通过mysql导入功能将所有查询导入mysql 如果有人能建议我如何进一步提高脚本的性能,那就太好了Php 解析和处理大型文件,php,mysql,Php,Mysql,我有一个大的CSV文件,我需要分为4部分,然后发送数据到数据库;我遇到的问题是CSV文件可能是1GB+(一次可能不止一个),这会造成各种时间延迟和内存问题 我想得到一些关于如何改进和加快流程的帮助 我正在测试的文件有45000条记录~10mb文件 现在我正在将文件加载到数组中,数组使用的大小大约是文件大小的3倍,所以对于10mb文件,我们说的是30mb内存;我希望通过逐行读取文件来减少对30mb内存的需求,但现在来看一下这个 处理部分相当简单,基本上我循环处理数据数组 最后一部分是将数据保存到数
更新1 现在我不再将文件加载到内存中,而是逐行处理文件。处理一个大文件不需要很长时间。处理500MB的数据文件需要几秒钟 在导入DB方面,我尝试了两种方法:
更新2 加载数据本地填充管理解决了一些硬盘问题;我还必须使用SplFileObject使文件读取对我来说更容易。我为LoadDataLocalInfle创建的文件仍然很大,但比以前好多了 目前,我必须在文件中执行循环,并存储信息所在位置的起点/终点,在执行此操作时,我创建了所有表,但需要外键的表除外。所以我所做的是: 表A和表B具有一对多关系:表A在第一个循环(通过文件的循环)处创建,此外,我们将表B的参数存储在表A中的单元格中 在第二个循环中,我们循环表A,从单元格中获取数据,并在表B中创建一组新行 在第一个循环中,我必须解析表B的参数,以提高第二个循环的性能 我在第二个循环中有很多foreach/for语句,因为第二个循环需要花费x4的时间才能完成 10MB文件当前性能如下:
- 第一圈6秒
- 第二圈12秒
- 平均总时间18-20秒
- 第一圈30秒
- 第二圈60秒
- 平均总时间90-100秒
- 第一圈3秒
- 第二圈16秒
- 平均总时间19-22秒
public function parseRawParam($line, $titles) {
$params = [];
$line = str_replace("\n", "", $line);
$rows = explode(",", $line);
for($row_i = 4; $row_i < count($rows); $row_i++) {
if(strlen(trim($rows[$row_i])) < 1) {
break;
}
$params[$titles[$row_i]] = $rows[$row_i];
}
return $params;
}
我一直在研究不同PHP版本之间的性能,PHP7比PHP5.6快得多,因此我希望升级PHP版本并提高性能。对于需要使用LOAD DATA INFILE的数据库。如果要对CSV数据进行任何数据更改,您应该能够构建一个包含行的文本文件,以便一次性批量插入到数据库表中。这将减少单表行插入的锁定,因为这样做成本很高
研究加载数据填充以将其分块…?这是一种时空权衡。你有多少空间或者你愿意牺牲多少时间。每个查询1行→ 非常慢,每个查询22k行→ 速度快,但内存需求巨大。最优解→ 我遇到的问题是,文件中有五个不同表的数据;其中两个有一对多的关系,我需要使用最后一个插入的ID,你不是要求它在一次点击中做太多。在进行其他插入时,是否可以将问题分解。ID的集合被收集在一个SELECT中,然后存储在一个数组中,并根据该数组进行查找,而不是针对每个ID查找数据库?如果出现故障,总会有一个更简单的解决方案。目前我正在考虑的一个解决方案是使用触发器。有关表格包括:记录和参数;1记录可能有许多参数。计划是在“记录”表中添加额外的列,用于存储参数;当插入行时,将触发如何从单元格中获取“参数”,并将新行插入“参数”表中。另一个解决方案是循环数据两次,非常简单
public function insertParam($record_id, $params) {
$sql = "";
foreach ($params as $param => $value) {
$sql = '"' . $record_id . '","' . str_replace("'", "\'", trim($param)) . '","' . trim($value) . '";';
}
return $sql;
}