Php 寻找一种更有效的方法在我的数据库中存储CSV数据
我每天都会收到一个.txt文件,其中包含分号分隔的数据。我的应用程序的用户每天都要将此文件上载到数据库 目前,我正在读取并存储以下信息:Php 寻找一种更有效的方法在我的数据库中存储CSV数据,php,mysql,laravel,Php,Mysql,Laravel,我每天都会收到一个.txt文件,其中包含分号分隔的数据。我的应用程序的用户每天都要将此文件上载到数据库 目前,我正在读取并存储以下信息: $array = array(); $csv = str_getcsv($request->file, "\n"); foreach ($csv as &$row) { $row = str_getcsv($row, ";"); $array[] = $row; } array_splice($array, 0, 1); for
$array = array();
$csv = str_getcsv($request->file, "\n");
foreach ($csv as &$row) {
$row = str_getcsv($row, ";");
$array[] = $row;
}
array_splice($array, 0, 1);
foreach ($array as &$row) {
$query = Table::firstOrNew(['col2' => $row[1], 'col3' => $row[2]]);
$query->col1 = $row[0];
$query->col2 = $row[1];
$query->col3 = $row[2];
$query->col4 = $row[3];
$query->col5 = $row[4];
// [...]
$query->col72 = $row[71];
$query->col73 = $row[72];
$query->save();
}
此方法的问题是,成功运行所需时间太长(每天的数据量约为5000条,使用上述代码需要约2分钟)。正如您所看到的,列的数量是巨大的,必须像处理.CSV文件一样读取数据,而且我根本不能丢弃任何列
更不用说,如果出于某种原因,一个用户(或多个用户)必须同时上传几天甚至一个月的数据,那么这个问题会大大增加
我需要想出更好的办法来处理这种情况。我到处寻找解决方案,但我能找到的最好办法是我应该使用
for
循环,而不是foreach
,这并没有真正解决问题。您正在检查每一行是否存在,如果存在,则更新,如果没有插入,对吗?
如果是这样,则无法优化此代码以加快运行速度,除非每行都有唯一的列,并在重复键更新时使用运行原始查询参见:
第二种解决方案是删除属于该文件或用户的所有旧记录,或者删除一些无法上载两次的唯一记录,然后使用insert
方法插入新行块
速度会快得多。范例
DB::beginTransaction();
try {
Table::where('unique_file_rows_identified_column', $something)->delete();
foreach(array_chunk($array, 1000) as $rows) {
$rows_to_insert = [];
foreach($rows as $row){
$rows_to_insert[] = [
'col1' => $row[0],
'col2' => $row[1],
'col3' => $row[2],
'col4' => $row[3],
'col5' => $row[4],
// [...]
'col72' => $row[71],
'col73' => $row[72],
];
}
Table::insert($rows_to_insert);
}
} catch (\Exception $e){ // If something went wrong and exception is thrown deleted rows will be restored
DB::rollBack();
dd($e->getMessage());
}
DB::commit();
如果文件包含5000行,则只运行5个查询,插入速度会快得多是否可以选择让数据库为您完成这项工作
将数据填充'/tmp/user_DATA.csv'加载到以';'结尾的表测试字段中;
当然,您需要确保CSV有效。谁使用这些数据?上传者是否拥有唯一的访问权限,还是所有人都可以访问?数据本身是否需要加载到数据库中,而不仅仅是保存路径?这需要用户两分钟的时间还是服务器两分钟的时间?我的意思是,用户可以在10秒钟后上传一个文件吗?所有用户都可以访问数据,并且在当前上传完成之前,用户无法上传另一个文件。这不会阻止其他用户上载。此外,数据需要加载到数据库中。当使用多个(批量)更新()/save()/::insert()时,最好使用try/catch