关于PHP操作MySql大数据量输出的方法
多表查询时,并且存在主从表的情况输出文件:
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+ 秒

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

单维表查询时输出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.6M
占用内存: 0.006M 执行时间: 1.558+秒

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