【问题标题】:Exporting a large CSV via PHP results in timeout/memory allocate error通过 PHP 导出大型 CSV 会导致超时/内存分配错误
【发布时间】:2018-02-02 22:43:50
【问题描述】:

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

没有改变 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 运行的,它不应该有超时,对吧?

【问题讨论】:

    标签: php csv timeout export


    【解决方案1】:

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

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

    【讨论】:

    • 这实际上会让脚本无限期地处理,对吗?对于这种情况,这是最佳做法吗?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 2020-11-04
      • 2019-03-25
      • 2017-01-05
      • 2012-11-27
      • 2018-08-23
      相关资源
      最近更新 更多