摘要:開發中經常遇到這樣的場景產品汪我要在后臺做一個功能,可以導出自定義時間范圍的訂單信息。結果,第二天一上班產品汪過來就是拍桌子,我想把去年一整年的訂單都導出來,結果后臺直接就掛了開發小哥一查,原來是內存溢出了,一年下來的的訂單量足足有條。
開發中經常遇到這樣的場景
產品汪:我要在后臺做一個功能,可以導出自定義時間范圍的訂單信息。開發小哥二話不說,半天就把功能做完并上線了。結果,第二天一上班產品汪過來就是拍桌子:MD,我想把去年一整年的訂單都導出來,結果后臺直接就掛了!
開發小哥一查,原來是內存溢出了,一年下來的的訂單量足足有1000W條。于是,開發小哥跟產品汪吵了起來:你TM色不色傻,1000W的數據你導出來干diao,你是不是想把服務器給搞掛掉?
于是,產品汪與程序狗就這么結下梁子了。
但是。產品的需求你敢這樣懟回去,那如果是老板提的這個需求呢,就是硬要把1000W條記錄導出來,你還不得乖乖回去碼代碼?
那么,這個如果真要導出這大量數據,該怎么做呢?開發中我們經常會使用框架來提高我們的開發效率,但也意味著框架會對一些數據進行封裝。
比如Yii2,當我們想獲取去年一年的訂單時,我們的代碼會這樣寫:
Order::find()->where("create_time between "2016-01-01" AND "2016-12-31"")->all();
當我們將上面代碼得到的結果集再拿去遍歷時,數據量一大,就會內存溢出。
原因是:Yii2中,對all方法進行了封將,將大量的數據存入了數組中,而遍歷大數據,必然會導致內存迅速上升。
那如何取出大量數據,而又不存到數組中呢?這就要用到了PHP中的迭代器:Iterator。如果有看過PDO::query的返回值類型的話,我們會發現,這個方法返回的PDOStatement,正是對Iterator的實現。關于Iterator,請自行腦補。
即然框架幫我們做了多余的封裝,那么我們就改用原生API來實現。以下是完整代碼
$sql = "select * from user"; $pdo = newPDO( "mysql:host=127.0.0.1;dbname=test", "root", "root" ); $pdo->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $rows = $pdo->query($sql); $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( $rows as $row ){ $line=[ $row["id"], $row["username"], $row["password"], $row["create_time"] ]; fputcsv($out,$line); } fclose($out); $memory=round((memory_get_usage()-$startMemory)/1024/1024,3)."M".PHP_EOL; file_put_contents("/tmp/test.txt",$memory,FILE_APPEND);
在表中生成7位數量級的記錄,執行上面的代碼,通過查看內存使用,發現整個過程只占用了0.XM的內存,完全沒有任何內存溢出的現象。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31623.html
摘要:環境適用場景需要處理一定數據集業務從讀取一定數據的業務導出一次需要處理一定的業務操作更新刪除等更多需要處理一定數據集的操作關鍵設置關鍵設置,如果不設置,依舊會從一次取出數據到里的游標屬性不是必須的生成器生成器,迭代數據操作本生成器可 環境 mysql: 5.6.34php: 5.6nginx: php-fpm 適用場景 需要處理一定數據集業務 從mysql讀取一定數據的業務導出 一次...
閱讀 1331·2019-08-30 15:44
閱讀 1381·2019-08-29 18:42
閱讀 433·2019-08-29 13:59
閱讀 770·2019-08-28 17:58
閱讀 2811·2019-08-26 12:02
閱讀 2414·2019-08-23 18:40
閱讀 2406·2019-08-23 18:13
閱讀 3106·2019-08-23 16:27