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

2022-08-30 15:28:45

目前,我正在为一个非常大的CSV文件编写一个导入脚本。问题是大多数时候它会在一段时间后停止,因为超时或会引发内存错误。

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

有没有更好的方法可以做到这一点,或者有人知道如何摆脱内存错误和超时?


答案 1

我使用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);
}

答案 2

我发现上传文件并使用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);

推荐