php直接导出csv,PHP百万级数据导出方案(生成器直接输出单个CSV)
概述:
之前寫過一篇文章叫PHP百萬級數據導出方案(多csv文件壓縮),發現很多朋友都很感興趣,但是當時用的方法比較不方便,可能不太符合很多人的需求。后來想了一下如何優化時,了解到能用生成器來處理內存溢出更方便,所以當時文章中也補充分享了一下這想法。然而,發現更多朋友對如何結合生成器導出數據感興趣,因此這篇文章,我來填下坑。
準備:
1、了解生成器yield
我上篇文章PHP百萬級數據導出方案(多csv文件壓縮) 說了幾個坑,大家可以先去回顧一下。然后我們可以看一下前輩的對生成器介紹的文章: PHP性能優化利器:生成器 yield理解,來理解一下生成器防止內存溢出的原理。
2、解決數據查詢內存溢出
了解完生成器yield原理之后,我們還需要解決一個問題,我們常用的mysql查詢函數是mysqli_query(connection,query,resultmode);,通常都是直接填寫第一第二個參數就直接查詢,但該函數默認的是對全部結果集進行緩存,這會導致數據過多的時候,內存也會溢出。因此,我們需要設置第三個參數為MYSQLI_USE_RESULT來逐行讀取結果集。那或許您有疑問為什么不直接 遍歷該mysqli_query()方法返回的結果來當每一行數據寫到CSV中,而還要用yield來存儲一次每行數據再寫到CSV中呢?其實這是因為mysqli_query()返回的結果是mysqli_result Object形式,而fputcsv()這個方法要求第二個參數為數組。所以yield的作用就是中轉站,但是他是一行行運輸數據,而不是讀多行來運輸數據。
代碼:<?php
/*
*?該方法是把數據庫讀出的數據進行CSV文件輸出,能接受百萬級別的數據輸出,因為用生成器,不用擔心內存溢出。
*?@param?string?$sql?需要導出的數據SQL
*?@param?string?$mark?生成文件的名字前綴
*
*/
function?putCsv($sql,?$mark)
{
set_time_limit(0);
header('Content-Type:?application/vnd.ms-excel;charset=utf-8');
header('Content-Disposition:?attachment;filename="'?.?$mark?.?'"');
header('Cache-Control:?max-age=0');
$file_num?=?0;??//文件名計數器
$fileNameArr?=?array();
$fp?=?fopen($mark?.'_'.$file_num?.'.csv',?'w');?//生成臨時文件
$fileNameArr[]?=?$mark?.'_'.$file_num?.'.csv';
fwrite($fp,?chr(0xEF).chr(0xBB).chr(0xBF));//轉碼,防止亂碼
foreach?(query($sql)?as?$a)?{
fputcsv($fp,?$a);
}
fclose($fp);??//每生成一個文件關閉
}
//生成器來緩存mysql查詢結果,返回類型為數組
function?query($sql){
$con?=?mysqli_connect("localhost",?"root",?"root");
if?(!$con)?{
die('Could?not?connect:?'?.?mysqli_error());
}
mysqli_select_db($con,?"dbmigs_smz");
mysqli_query($con,'set?names?utf8');
$n?=?0;
//????print_r(mysqli_query($con,?$sql,MYSQLI_USE_RESULT)?);?mysqli_result?Object?返回
//該處用MYSQLI_USE_RESULT?就是不緩存結果集中,也是為了避免內存溢出,相當于mysql_unbuffered_query
foreach?(mysqli_query($con,?$sql,MYSQLI_USE_RESULT)?as?$row?){??//
yield?$row;
echo?$n++??.?"
";??//輸出行數
}
$con->close();
}
//$sql?=?'SELECT?id,ArticleClassify,ArticleTitle?FROM?`test_yield`??where?id?
$sql?=?'SELECT?id,ArticleClassify,ArticleTitle?FROM?`test_yield`??where?id?
$mark?=?'test';
putCsv($sql,$mark,1,2);
?>
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的php直接导出csv,PHP百万级数据导出方案(生成器直接输出单个CSV)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个游戏策划案(仅供参考)
- 下一篇: Unity_游戏源码