0

为了避免服务器超载,我做了一个queryen循环,我会得到150k个成员并存储在一个数组中。这很好用,但是当循环完成它的工作时,必须打印出数组,但这需要很长时间,并且最终会导致侧面崩溃。

$development = array(
    'testing' => false,
    'testing_loops' => 1
    );

$settings = array(
    'times_looped' => 0,
    'members_at_a_time' => 2000,
    'print_settings' => true,
    'members_looped' => 0,
    'test' => 0,
);


function outputCSV($data) 
    {

    $outstream = fopen("php://output", 'w');

    array_walk($data, '__outputCSV', $outstream);

    fclose($outstream);
    }

function __outputCSV(&$vals, $key, $filehandler) 
    {
        fwrite($filehandler, implode(',',$vals). "\n");
    }


function getMembers(&$settings, $ee)
{

    // SQL FROM
    $sql_from = $settings['times_looped'] * $settings['members_at_a_time'];

    // SQL LIMIT
    $sql_limit = $sql_from . ', ' . $settings['members_at_a_time'];

    $settings['test'] = $sql_limit;

    // GET MEMBERS
    $query = $ee->EE->db->query("SELECT m.email,
    cr.near_rest_1_id, cr.near_rest_1_distance, 
    cr.near_rest_2_id, cr.near_rest_2_distance,
    cr.near_rest_3_id, cr.near_rest_3_distance
    from exp_members m
    left join 
    exp_menucard_closest_restaurants cr
    on m.member_id = cr.member_id
    where group_id = 8 or 14 limit ".$sql_limit."");      

    // Check if members found
    if($query->num_rows() == 0)
    {
        return $query->num_rows();
    }

    // Update number of members
    $settings['members_looped'] = $settings['members_looped'] + $query->num_rows();

    // Loop members
    foreach($query->result_array() as $row) {

       if($row['near_rest_1_distance'] > 1.0)
        {$near_rest_1_distance= number_format($row['near_rest_1_distance'], 2, ',', ',') ." ". 'km';}

        else
        {$near_rest_1_distance= number_format($row['near_rest_1_distance'], 3, ',', '')*1000 ." ". 'meter';}

        if($row['near_rest_2_distance'] > 1.0)
        {$near_rest_2_distance= number_format($row['near_rest_2_distance'], 2, ',', ',') ." ". 'km';}

        else
        {$near_rest_2_distance= number_format($row['near_rest_2_distance'], 3, ',', '')*1000 ." ". 'meter';}

        if($row['near_rest_3_distance'] > 1.0)
        {$near_rest_3_distance= number_format($row['near_rest_3_distance'], 2, ',', ',') ." ". 'km';}

        else
        {$near_rest_3_distance= number_format($row['near_rest_3_distance'], 3, ',', '')*1000 ." ". 'meter';}

         $nearest_rest_result_array[] = array(
        'email' =>  $row['email'],
        'near_rest_1_id' =>  $row['near_rest_1_id'],
        'near_rest_1_distance' => $near_rest_1_distance,
        'near_rest_2_id' =>  $row['near_rest_2_id'],
        'near_rest_2_distance' =>  $near_rest_2_distance, 
        'near_rest_3_id' => $row['near_rest_3_id'],
        'near_rest_3_distance' =>  $near_rest_3_distance
        ); 

    }

    // Loop again
    return $query->num_rows();
}


// Loop
$more_rows = true;
while($more_rows == true || $more_rows > 0) 
{

    // Test
    if($settings['times_looped'] >= $development['testing_loops'] && $development['testing'] == true){
        break;

    }
    // get members
    $more_rows = getMembers($settings, $this);
    $settings['members_looped'] = $settings['members_looped'] + $more_rows;
    $settings['times_looped']++;

    // Got last bunch of members
    if($settings['members_looped'] < $settings['members_at_a_time'])
    {
        break;

    }

}

当循环完成其工作时,它将打印出所有数组

// Write to CSV
outputCSV($nearest_rest_result_array);
4

3 回答 3

3

不要使用 foreach 循环。使用while-loop 从数据库中读取行并将其写入 CSV 文件。这样,您就可以逐行操作,而不会使用太多内存。

如果您正在处理大型数据集,通常最好有一些迭代器或流的概念,而不是尝试在一个大操作中修改整体。

于 2013-08-30T11:52:09.637 回答
2

错误很早就开始了,请使用迭代器而不是您当前执行的数组:

foreach($query->result_array() as $row)

PDO 和 Mysqli 允许迭代结果。即时创建输出并将其流式传输到客户端,您的网络服务器将正常分块,如果没有,请将您的 PHP 输出缓冲区设置为 4096k 或类似。

于 2013-08-30T11:53:47.917 回答
0

考虑在您的网页中实现分页。

让我们举个例子。假设您的数据库有 10,000 行。可能不需要一次显示这 10,000 行。相反,我们可以每页显示 100 条记录,并有 100 个这样的页面的链接。

最好的例子可以是https://www.google.co.in/?gws_rd=cr&ei=-HggUuXWBMj4rQeNr4CADw#q=pagination+in+php

在 6,190,000 个结果中,每页仅显示 11 个。

于 2013-08-30T11:55:36.437 回答