关于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+秒
以上测试用例, 正式用可根据实际情况调整即可