Php 使用mysql加载数据填充处理大型csv文件
我正在尝试读取包含500k行和81列的CSV文件,并将其插入数据库。CSV大小为160 MB。我必须每3-4小时处理一次。每3-4小时,我将有一个新的CSV,其中包含一些新记录和一些现有记录。为此,我采用了许多方法,但没有一种方法是完美的 方法1:它读取所有记录,但花费太多时间。读取20万条记录需要1个多小时,然后超时Php 使用mysql加载数据填充处理大型csv文件,php,mysql,csv,pdo,laravel-5.3,Php,Mysql,Csv,Pdo,Laravel 5.3,我正在尝试读取包含500k行和81列的CSV文件,并将其插入数据库。CSV大小为160 MB。我必须每3-4小时处理一次。每3-4小时,我将有一个新的CSV,其中包含一些新记录和一些现有记录。为此,我采用了许多方法,但没有一种方法是完美的 方法1:它读取所有记录,但花费太多时间。读取20万条记录需要1个多小时,然后超时 $file = fopen($path, 'r'); while (($line = fgetcsv($file)) !== FALSE) { } 作为一个解决方案:我可
$file = fopen($path, 'r');
while (($line = fgetcsv($file)) !== FALSE) {
}
作为一个解决方案:我可以增加php限制、执行时间和内存限制来避免这个错误,但我觉得它非常慢
方法2:
$query = "LOAD DATA LOCAL INFILE products.csv INTO TABLE tmp_tbl LINES TERMINATED BY '\\r\\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES";
DB::select($query);
它给出了以下错误
SQLSTATE[42000]:语法错误或访问冲突:1064您有
SQL语法错误;检查与您的产品相对应的手册
MariaDB服务器版本,以获取使用“近”字段的正确语法
终止于第1行的“忽略1行”(SQL:LOAD DATA LOCAL
将“products.csv”填充到以“\r\n”结尾的表tmp\u tbl行中
以“,”结尾的字段(忽略1行)
方法3:
$query = "LOAD DATA LOCAL INFILE 'products.csv' INTO TABLE tmp_tbl LINES TERMINATED BY '\\r\\n' FIELDS TERMINATED BY ',' IGNORE 1 LINES";
DB::connection()->getpdo()->exec($query);
或
出现以下错误
SQLSTATE[42000]:语法错误或访问冲突:1064您有
SQL语法错误;检查与您的产品相对应的手册
MariaDB服务器版本,以获取使用“近”字段的正确语法
终止于第1行的“忽略1行”
方法4
$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl";
DB::connection()->getpdo()->exec($query);
出现以下错误
PDO::exec():MySQL服务器已离开
方法5
$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl";
DB::select($query);
出现以下错误
SQLSTATE[HY000]:一般错误:2014无法在
其他未缓冲查询处于活动状态。考虑使用
PDO语句::fetchAll()。或者,如果您的代码只是
要在mysql上运行,可以通过设置
PDO::MYSQL\u ATTR\u USE\u BUFFERED\u查询属性。(SQL:加载数据)
本地将“products.csv”填入表格tmp(待定)
我应该继续使用哪种方法?为什么会出现这些错误?我希望在更短的时间内处理所有记录而不出现任何错误。尝试添加以下内容:
DB::connection()->disableQueryLog()代码>到脚本顶部-内存消耗可能来自于在内存中存储查询。为什么方法1需要占用这么多内存?在循环该数组以将所有记录插入数据库之前,您是否试图从csv中构建一个数组以将其插入数据库?不,我不是在使用数组,我是在使用fgetcsv逐个访问行并在数据库中插入/更新。这样,无论如何,内存使用率都不会很高;速度可能是个问题,但你不应该成为增加记忆的理由。有什么建议可以让我在方法1中加快处理速度吗?将一个初始文件拆分成几个小文件,并使用几个线程并行处理它们。@Jass-方法1是。
$query = "LOAD DATA LOCAL INFILE '".$file_path."' INTO TABLE tmp_tbl";
DB::select($query);