情况是我需要将一个相当大的 csv 文件(大约 1/2 百万条记录 - 80mb)导入到 mysql 数据库中。我知道我可以从命令行执行此操作,但我需要 UI,以便客户端可以执行此操作。
这是我到目前为止所拥有的:
ini_set('max_execution_time', 0);
ini_set('memory_limit', '1024M');
$field_maps = array();
foreach (Input::get() as $field => $value){
if ('fieldmap_' == substr($field, 0, 9) && $value != 'unassigned'){
$field_maps[str_replace('fieldmap_', null, $field)] = $value;
}
}
$file = app_path().'/../uploads/'.$client.'_'.$job_number.'/'.Input::get('file');
$result_array = array();
$rows = 0;
$bulk_insert_count = 1000;
if (($handle = fopen($file, "r")) !== FALSE)
{
$header = fgetcsv($handle);
$data_map = array();
foreach ($header as $k => $th){
if (array_key_exists($th, $field_maps)){
$data_map[$field_maps[$th]] = $k;
}
}
$tmp_rows_count = 0;
while (($data = fgetcsv($handle, 1000)) !== FALSE) {
$row_array = array();
foreach ($data_map as $column => $data_index){
$row_array[$column] = $data[$data_index];
}
$result_array[] = $row_array;
$rows++;
$tmp_rows_count++;
if ($tmp_rows_count == $bulk_insert_count){
Inputs::insert($result_array);
$result_array = array();
if (empty($result_array)){
echo '*************** array cleared *************';
}
$tmp_rows_count = 0;
}
}
fclose($handle);
}
print('done');
我目前正在本地 vagrant box 上工作,当我尝试在本地运行上述代码时,它会处理 csv 文件的几乎所有行,然后在结束前不久就死掉(没有错误),但它会占用盒子内存限制为 1.5Gb。
我怀疑我在上面的代码中所做的一些事情是不必要的,例如但我认为通过构建和插入有限数量的行可以减少内存使用,但这还不够。
我怀疑这可能会在具有更多可用内存的实时服务器上工作,但我无法相信它必须占用 1.5Gb 内存来处理 80mb 文件,必须有更好的方法。非常感谢任何帮助
最佳答案
曾经遇到过这个问题,这为我解决了:
DB::connection()->disableQueryLog();
关于PHP - 为什么读取这个 csv 文件使用这么多内存,我该如何改进我的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21163761/