通过 PHP 导出大型 CSV 会导致超时/内存分配错误



我有一个工具,允许根据不同的时间范围导出数据。我遇到的问题是时间范围越长,数据越多,最终数据集太大 - 导致超时错误或内存分配错误。

除了更改 php.ini 以获得更大的max_execution_time等之外,有没有更好的方法可以做到这一点?

这是我构建CSV的脚本(用户选择导出,然后加载此页面):

$fileName           = "export-".date("YmdHis");
$exportSignature    = array(" ","Export","Generated by: ".$_SESSION['name'],date("Y-m-d H:i:s"));
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename='.$fileName.'.csv');
// create a file pointer connected to the output stream
$output = fopen('php://output', 'w');
// run all the queries for the data
if($exportType == "list") {
include('include/query-compare.php');   
} elseif($exportType == "analyze") {
include('include/query-analyze.php');   
} elseif($exportType == "funnel") {
include('include/query-funnel.php');    
} elseif($exportType == "funnelTrend") {
include('include/query-funnel-trends.php'); 
}
// add column headers
fputcsv($output,$columnHeaders);
// add row data
if($exportType == "list") {
foreach($comparison as $account) {
fputcsv($output,$account);
}
} elseif($exportType == "analyze") {
foreach($analyze as $account) {
fputcsv($output,$account);  
}
} elseif($exportType == "funnel" || $exportType == "funnelTrend") {
foreach($funnel as $line) {
fputcsv($output,$line); 
}
}   
// add export signature
foreach($exportSignature as $line) {
fputcsv($output,array($line));
}

下面是用于创建行的数组示例。这是变量 -- 如果时间范围很小,数组中可能有几百个条目,如果时间范围很大,则有数万个条目。

Array
(
[0] => Array
(
[0] => 1
[firstName] => Marco
[lastName] => R.
[title] => D
[email] => test@test.com
[company] => xx
[lSource] => xx
[lDetail] => xx
[lExact] => xx
[createdAt] => 2017-06-26 00:00:00
[nDate] => 2017-08-15
[cDate] => 2017-08-15
[cMoment] => xx
[mDate] => 2017-08-15
[mMoment] => xx
[Id] => 003Axx
[Type] => Contact
[accountId] => 001A0xx
[parentAccountId] => 
[accountOwner] => Kevin S.
[xx] => Nicholas W.
[accountType] => Prospect
[totalARR] => 0.00
[accountTier] => 
[ty] => XX
[industry] => Corporate Services
[secondaryIndustry] => IT Services and Consulting
[billingCountry] => Germany
[1] => 006Axx
[2] => PS (New Business)
[3] => Kevin S.
[4] => Nicholas W.
[5] => cc
[6] => New Business
[7] => Identify
[8] => 40000.00
[9] => 2017-08-16
[10] => 2018-07-27
[11] => 2017-08-16
[12] => 2017-08-21
)
)

我可以安排导出并将其通过电子邮件发送给用户,我只是不熟悉如何在后台构建这个大型 CSV 而不会超时。

编辑:在数据库中将导出排队并有一个 cron 作业来查找导出,然后在后台运行导出直到完成,这是一个更好的选择吗?由于它是通过 cron 运行的,所以它不应该有超时,对吧?

在文件的开头使用set_time_limit ( 0 );。例如:

set_time_limit ( 0 );
$fileName           = "export-".date("YmdHis");

使用set_time_limit ( 0 );没有帮助,因为我在nginx上运行并且会遇到网关错误。相反,我最终将下载排队到数据库表中,并通过 cron 作业执行实际查询,因为这些查询不受相同的超时限制。

相关内容

  • 没有找到相关文章

最新更新