PHP - 为什么读取这个 csv 文件使用这么多内存,我该如何改进我的代码?

标签 php mysql csv import laravel

情况是我需要将一个相当大的 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();

文档中有关它的信息:http://laravel.com/docs/database#query-logging

关于PHP - 为什么读取这个 csv 文件使用这么多内存,我该如何改进我的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21163761/

相关文章:

php - mysql WHERE 语句中的字符串数组值

PHP is_dir 和 mkdir 不能在映射的网络驱动器上工作

javascript - NodeJS - mysql 包尊重完成 INSERT INTO...SET 后的列名称?

javascript - 内置 PhantomJs 和 php 吗?

php - 我究竟应该把 SESSION_START 放在哪里?

php - Facebook 动态消息 API

mysql - 如何对长字符串进行数据库规范化?

java - openCSV 解析各个列

powershell - 具有重复列标题的 Import-Csv powershell

javascript - d3 : how can I load external CSV file into data?