处理非常大的csv文件,没有超时和内存错误

时间:2011-09-06 10:57:31

标签: php csv import timeout

目前我正在编写一个非常大的CSV文件的导入脚本。问题大多数情况是由于超时而在一段时间后停止或者引发内存错误。

我的想法现在是以“100行”步骤解析CSV文件,然后100行自动调用脚本。我尝试使用标题(位置...)来实现这一点并使用get传递当前行但是它没有按照我想要的那样工作。

有没有更好的方法或有人知道如何摆脱内存错误和超时?

4 个答案:

答案 0 :(得分:51)

我已经使用fgetcsv以流方式读取120MB csv(这是正确的英语吗?)。它逐行读取,然后我将每一行插入数据库。这样,每次迭代只在内存中保留一行。剧本仍然需要20分钟。跑步。也许我下次尝试使用Python ...不要尝试将巨大的csv文件加载到数组中,这样会占用大量内存。

// WDI_GDF_Data.csv (120.4MB) are the World Bank collection of development indicators:
// http://data.worldbank.org/data-catalog/world-development-indicators
if(($handle = fopen('WDI_GDF_Data.csv', 'r')) !== false)
{
    // get the first row, which contains the column-titles (if necessary)
    $header = fgetcsv($handle);

    // loop through the file line-by-line
    while(($data = fgetcsv($handle)) !== false)
    {
        // resort/rewrite data and insert into DB here
        // try to use conditions sparingly here, as those will cause slow-performance

        // I don't know if this is really necessary, but it couldn't harm;
        // see also: http://php.net/manual/en/features.gc.php
        unset($data);
    }
    fclose($handle);
}

答案 1 :(得分:16)

我发现上传文件并使用mysql的LOAD DATA LOCAL查询快速解决方案,例如:

    $sql = "LOAD DATA LOCAL INFILE '/path/to/file.csv' 
        REPLACE INTO TABLE table_name FIELDS TERMINATED BY ',' 
        ENCLOSED BY '\"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES";
    $result = $mysqli->query($sql);

答案 2 :(得分:13)

如果您不关心它需要多长时间以及需要多少内存,您可以简单地增加此脚本的值。只需将以下行添加到脚本顶部:

ini_set('memory_limit', '512M');
ini_set('max_execution_time', '180');

使用函数memory_get_usage(),您可以找出脚本需要多少内存来为memory_limit找到一个好的值。

您可能还想查看fgets(),它允许您逐行读取文件。我不确定这是否需要更少的内存,但我真的认为这会起作用。但即使在这种情况下,您也必须将max_execution_time增加到更高的值。

答案 3 :(得分:-3)

喔。只需将此脚本称为CLI,而不是通过愚蠢的Web界面。因此,没有执行时间限制会影响它 并且不要永远保留解析结果,而是立即将其写下来 - 因此,您也不会受到内存限制的影响。