【问题标题】:import/export big files, avoiding memory exhausted errors导入/导出大文件,避免内存耗尽错误
【发布时间】:2014-02-26 23:02:04
【问题描述】:

在我的应用程序中,我有一个导入功能,它允许用户将数据从 csv 文件导入我的应用程序以及导出现有数据)。

问题是导入的文件可能有很多记录,在导入方法中我创建了很多相关的对象,所以在某些情况下会导致内存耗尽错误。

我正在寻找优化我的代码的方法。我已经在使用 $em->clear 和 gc_collect_cycles 函数,而且我知道 Doctrine2 批处理方法。 是否可以创建一个仅用于导入文件的后台进程(例如运行控制台命令?

这种情况的最佳做法是什么? 例如,我知道 OroCrm 项目对其安装程序使用命令,同时向用户显示加载程序,并且他们的安装运行非常顺利。

期待您的意见。 谢谢。

【问题讨论】:

    标签: php symfony memory import background-process


    【解决方案1】:

    您当然可以运行控制台命令。但 Doctrine 2 不适合批量操作,很快就会耗尽 gas。

    我有一个使用 PDO 的进程,它会定期扫描包含 110K 记录的 csv 文件并更新多达五个不同的表。即使在我每月 5 美元的共享主机服务器上也能正常运行。

    制作 PDO 服务:

    # =============================================================
    pdo:
        class: PDO
        arguments:
            dsn:      '%database_dsn%'      # mysql:dbname=appgames
            user:     '%database_user%'
            password: '%database_password%'
        calls:
            - [setAttribute, [ 3, 2]] # \PDO::ATTR_ERRMODE,           \PDO::ERRMODE_EXCEPTION
            - [setAttribute, [19, 2]] # \PDO::ATTR_DEFAULT_FETCH_MODE \PDO::FETCH_ASSOC
            - [setAttribute, [20, 0]] # \PDO::ATTR_EMULATE_PREPARES
    

    准备一些语句:

    public function prepareLevelInsert()
    {
        $key = 'levelInsert';
    
        if (isset($this->prepared[$key])) return $this->prepared[$key];
    
        $sql = <<<EOT
    INSERT INTO levels
           ( id,  name, sport, domain, domainSub, status)
    VALUES (:key,:name,:sport,:domain,:domainSub, 'Active')
    ;
    EOT;
        return $this->prepared[$key] = $this->conn->prepare($sql);
    }
    

    然后扫描你的文件

    // $conn is the PDO object or a 
    // DBAL connection object obtained from $entityManager->getConnection();
    $conn->beginTransaction();
    while($row = fgetcsv($fp))
    {
        // Pull level data
        $level = array('name' => $row['levelName'] ... rest of values ...);
    
        // And insert
        $this->prepareLevelInsert()->execute($level);
    }
    $conn->commit();
    

    也许有点乏味,但比使用 Doctrine 2 快很多。

    【讨论】:

      猜你喜欢
      • 2010-12-15
      • 2014-07-28
      • 1970-01-01
      • 2017-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      相关资源
      最近更新 更多