目前我正在编写一个非常大的CSV文件的导入脚本。问题大多数情况是由于超时而在一段时间后停止或者引发内存错误。
我的想法现在是以“100行”步骤解析CSV文件,然后100行自动调用脚本。我尝试使用标题(位置...)来实现这一点并使用get传递当前行但是它没有按照我想要的那样工作。
有没有更好的方法或有人知道如何摆脱内存错误和超时?
答案 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界面。因此,没有执行时间限制会影响它 并且不要永远保留解析结果,而是立即将其写下来 - 因此,您也不会受到内存限制的影响。