如何使 CSV 上传执行得更快?

Posted

技术标签:

【中文标题】如何使 CSV 上传执行得更快?【英文标题】:How to make a CSV upload perform faster? 【发布时间】:2012-01-10 18:30:15 【问题描述】:

我想知道你们中是否有人尝试过以实时形式(多部分/表单数据)进行 CSV 迁移,我唯一讨厌的是它消耗大量时间并且达到了最大值执行超时。我所做的快速修复是通过在我的 php.ini(或 set_time_limit()) 中设置最大执行时间,但等待半小时才导入整个数据真的很烦人,尽管它不超过 100kb。是我反应过度还是怎么的?

这是代码:

function upload($id, $old_eid)


    $filename = $_FILES['event_file']['tmp_name'];
    $handle = fopen($filename, "r");

    while(($data = fgetcsv($handle, 1000, ",")) !== FALSE)
        $id  = $id;
        $id2 = $data[2];
        $ckr = $this->Manager_model->check_if_record_exists($id, $id2);

        if(count($ckr) > 0):
            $this->session->set_flashdata('err', '<div class="error">Duplicated record</div>');
            redirect("manager/csver/$id");
        else:
            $data['col1'] = $data[0];
            $data['col2']  = $id;
            $data['col3'] = $data[3].' '.$data[4];
            $data['col4']  = $data[2];
            $data['col5'] = $data[6];
            $data['col6']  = $data[1];
            $data['col7']  = $data[7];

            $data['col8']  = mt_rand(11111, 99999);
            $data['col9']   = $old_eid;

            $this->Manager_model->add_csv($data);
            $this->Manager_model->add_csv_to_photo($data);

        endif;
    
        fclose($handle);
        $this->session->set_flashdata('success', '<div class="success">CSV successfully uploaded</div>');
        redirect("manager/records/$id");
        //$this->session->set_flashdata('msg', '<div class="success">Records successfully uploaded</div>');
 

我的 Manager_model:

 function add_csv($data)

    $src = array(
            'col1'=> $data['col1'],
            'col2'    => $data['col2'],
        'col3' => $data['col3'],
        'col4'  => $data['col4'],
        'col5' => $data['col5'],
        'col6'  => $data['col6'],
        'col7' => $data['col7'],
        'col8' => $data['col8'],
    );
    $this->db->insert('e_records2', $src);

    if($this->db->affected_rows() == '1'):
        return TRUE;
    endif;

    return FALSE;


function add_csv_to_photo($data) 
    $src = array(
            'col1'=> $data['col1'],
               'col2' => $data['col2'],
                'col3' => $data['col3'],
                'col4' => $data['col4'],
                'col5'=> $data['col5'],
                'col6'=> $data['col6'],
    );
    $this->db->insert('e_records', $src);

    if($this->db->affected_rows() == '1'):
        return TRUE;
    endif;

    return FALSE;
 function check_if_record_exists($id, $id2) 

    $eid = $id;
    $id2 = $id2;
    $query = $this->db->query("select * from races_results where eid = $eid AND id2 = $id2");
    return $query->result();

附: 我不是在这里谈论 PhpMyAdmin,因为我知道导入 csv 文件是如何工作的。此外,使用骨骼迁移文件会产生很多琐碎的任务。

【问题讨论】:

你在用这些数据做什么? 30 分钟来处理 100KB 太慢了。 您可能想要发布您正在使用的“工作”代码的 sn-p。 我不认识,但这真的很烦人,也许是因为我正在导入两个不同的表 + 检查该行是否与之前的行相同。可能是?我不知道。但它应该不会吃那么多时间吧? @xxxo_tryme 向我们展示您的代码,我们会告诉您 @xxxo_tryme 啊哈,可能这个行检查算法效率真的很低。 【参考方案1】:

为什么不运行分析器来优化您的代码? Codeigniter 包含这个有用的部分来解决像这样的问题http://codeigniter.com/user_guide/general/profiling.html

它将为您提供 SQL 查询的细目,以及需要花费的时间和位置。

$this-&gt;output-&gt;enable_profiler(TRUE);

【讨论】:

【参考方案2】:

在我看来,问题在于您在 CSV 文件中的每行查询数据库一次(或两次?)。 当然你会得到糟糕的表现。 您可以一次性完成整个查询,并让数据库立即为您制作 CSV。

SELECT DISTINCT f1,f2,f3,... FROM tablex WHERE .. INTO OUTFILE 'c:/dir/ca.csv' 
  FIELDS ESCAPED BY '"' FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n';
//note the use of forward slashes even on Windows.

见:http://dev.mysql.com/doc/refman/5.0/en/select-into.html

选择本身的速度是这里的限制因素。 确保您对该目录具有写入权限,并注意 MySQL 永远不会覆盖文件。 这个命令在 MySQL 上非常快。

【讨论】:

【参考方案3】:

$id = $id;

真的吗?

$ckr = $this->Manager_model->check_if_record_exists($id, $id2);

加快速度的一个明显方法是在 eid 和 id2 上设置唯一索引,并忽略 INSERT 上的重复行错误。

但实际上,如果您希望它运行得更快,只需 tell mysql to parse and load the data。

【讨论】:

以上是关于如何使 CSV 上传执行得更快?的主要内容,如果未能解决你的问题,请参考以下文章

如何使MongoDB更新执行得更快?

在 C++ 中通过 csv 文件的更快方法

如何让我的 python 程序运行得更快?

如何使这个 mysqli 查询在 PHP 中运行得更快?

如何使用 parRF 方法使随机森林运行得更快

如何使此代码运行得更好/更快(线程或多处理)?怎么做?