关于PHP操作MySql大数据量输出的方法

分类:PHP |

多表查询时,并且存在主从表的情况输出文件:  

function testMultiTable()
{
    $start_memory = memory_get_usage();
    $start_time = Utils::microtime();
    $sql = 'select a.*,b.name,b.member_name,s.shop_name,w.warehouse_name,c.channel_name,a.pay_amount-a.paid no_paid,cc.*
            from xxx.bd_order a
            inner join xxx.md_member b on a.member_id=b.member_id
            inner join xxx.sy_shop s on a.shop_id=s.shop_id
            inner join xxx.md_warehouse w on a.warehouse_id=w.warehouse_id
            inner join xxx.bd_order_item_detail as cc on a.order_id=cc.order_id
            inner JOIN xxx.md_channel c on c.channel_id = b.channel_id order by a.order_id desc';
    foreach ($this->_multiTable($sql, 'order_id') as $v) {
        file_put_contents('/tmp/testx.txt', json_encode($v) . PHP_EOL, FILE_APPEND);
    }
    $memory = round((memory_get_usage() - $start_memory) / 1024 / 1024, 3) . 'M' . PHP_EOL;
    echo $memory . PHP_EOL;
    echo Utils::microtime() - $start_time;
    exit;
}

function _multiTable($sql, $field)
{
    $pdo = \Yii::$app->db->slavePdo;
    $pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
    $rows = $pdo->query($sql, \PDO::FETCH_ASSOC);
    $last_id = '';
    $last_row = [];
    foreach ($rows as $key => $row) {
        if ($last_id == $row[$field] && !empty($last_row)) {
            $last_row['detail'][] = $row;
            continue;
        } else if (!empty($last_row)) {
            yield $last_row; // 返回上一条记录
        }
        $last_row = $row;
        $last_row['detail'][] = $row;
        $last_id = $row[$field];
    }
    yield $last_row; // 返回最后一条记录
}

占用内存 0.02M 和 执行时间:22.039+ 秒

image.png

共输出: 879M, 使用22秒左右

image.png


单维表查询时输出csv文件, sql可以是单表,也可以联查表情况: 

    function testSingleTable()
    {
        $start_memory = memory_get_usage();
        $start_time = Utils::microtime();
        $sql = 'SELECT * FROM xxx.bd_order_item_detail';
        $filename = date('Ymd') . '.csv'; //设置文件名
        header('Content-Type: text/csv');
        header("Content-Disposition: attachment;filename={$filename}");
        $out = fopen('php://output', 'w');
//        fputcsv($out, ['id', 'username', 'password', 'create_time']);
        foreach ($this->_singleTable($sql) as $row) {
//            $line = [$row['id'], $row['username'], $row['password'], $row['create_time']];
            fputcsv($out, $row);
        }
        fclose($out);
        $memory = round((memory_get_usage() - $start_memory) / 1024 / 1024, 3) . 'M' . PHP_EOL;
        $use_time = Utils::microtime() - $start_time;
        file_put_contents('/tmp/test.txt', $memory, FILE_APPEND);
        file_put_contents('/tmp/test.txt', $use_time, FILE_APPEND);

        exit;
    }

    function _singleTable($sql)
    {
        $pdo = \Yii::$app->db->pdo;  //  $pdo = new \PDO('mysql:host=127.0.0.1;dbname=xxx', 'root', '123456');
        $pdo->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
        $rows = $pdo->query($sql, \PDO::FETCH_ASSOC);
        $i = 0;
        foreach ($rows as $row) {
            $i++;
            $row['tmp_id'] = $i;
            yield $row;
        }
    }


生成CSV 文件48.6Mimage.png

占用内存: 0.006M    执行时间: 1.558+秒

image.png



以上测试用例, 正式用可根据实际情况调整即可