【问题标题】:Large data set import in Symfony 2Symfony 2 中的大型数据集导入
【发布时间】:2012-12-13 03:38:33
【问题描述】:

我正在开发一个基于 Symfony 2 的项目,需要使用 cron 任务定期从 .csv 文档中导入 150 万个产品。

导入当前如下所示:

    ...

    Propel::disableInstancePooling();

    $fp = fopen($file, 'r');
    while ( !feof($fp) ) {
        $line = fgets($fp, 2048);
        $data = str_getcsv($line, "\t");

        $product = new Product();
        $product->setId($data[0]);
        $product->setTitle($data[1]);
        ...
        $product->save();
    }

    ...

但是大约 5 分钟后,Apache 达到其 512MB 内存分配并引发以下错误:

Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 78 bytes) in /var/www/vhosts/myapp.local/app/cache/dev/classes.php on line 9451

我已经禁用了 Propel 的实例池(这在过去在其他框架中的 Propel 驱动的导入中一直有效)并且问题仍然存在,所以我想知道 Symfony 2 是否正在执行任何类型的缓存(基于错误被抛出)。

有没有人有任何在 Symfony 2 中执行大型导入的经验,可以为我指明正确的方向?

【问题讨论】:

    标签: php symfony propel


    【解决方案1】:

    其实这个导入应该直接在mysql级别进行(mysql可以从csv文件中读取数据),除非很复杂。另一种方法是增量读取文件,生成一个 sql 文件,然后本地将其导入数据库。没有理由让 Web 应用程序直接处理如此大的导入,因为您将耗尽内存。

    确保您不会一次将整个 csv 加载到内存中。

    另外的解决方案是在php.ini中给php更多的内存,希望最好。 php 不是批量处理大量数据的最佳语言。

    【讨论】:

    • 好的,我会看看在 MySQL 级别上导入它。这种规模的数据导入对我来说是新领域。您正确地提到 PHP 不是用于修补处理此级别数据的最佳语言。您是否建议我将 Python 视为替代方案?谢谢。
    • 视情况而定。只要你预处理数据(如果你没有以原生格式接收它,比如 mysql 的 sql 语句)并且你小心资源消耗(所以你不会耗尽内存),你可以将数据转换为mysql 可以理解的格式。一种方法是从文件中读取前 x 行,将生成的 sql 转储到文件中。像这样继续阅读,直到完成整个文件。一旦你有了 sql,就让 mysql 客户端去做它的工作。它会比你做的更快。但请注意,测试您的脚本。由于脚本不佳,我看到太多数据丢失。
    • 老实说,我不确定 python 是否更好,c 是否更好,或任何其他语言。您只需要注意资源并明智地使用它们。 mysql 客户端将完成大部分时间。
    • 我使用了 MySQL 的 load data infile 函数,它似乎做得很好!我将 10 多分钟的导入时间缩短为 10 秒!
    【解决方案2】:

    哦,男孩,我 6 个月前在那里,给你一个小字:交易。

    将 csv 切成小块,例如在 10000 行或多或少的包中,每个包执行 1 个事务,这样您就可以避免将 150 万次写入 db 并写入 150 次的开销。

    希望能指导您找到一个好的解决方案,我无法将我的时间从 30 秒缩短,也许您应该考虑为这类 io/cpu 绑定任务使用离线任务处理器。

    此刻这个页面是我的圣经: http://propelorm.org/documentation/06-transactions.html

    编辑

    实际上,我认为这是网站要求的某种导入操作,如果这是您“开发人员”需要做的一次性事情,我会接受 Xnoise 的建议。

    【讨论】:

    • 感谢您的回复。我正在考虑用 C# 编写一些东西来离线执行,但理想情况下我需要它每 2 或 3 天运行一次,并且希望避免手动处理数据的麻烦。
    • Python 会毫不费力地做到这一点,csv 模块很好,看看这个。 stackoverflow.com/questions/10154633/…
    猜你喜欢
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 2011-06-26
    相关资源
    最近更新 更多