成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

PHP+MySQL導(dǎo)出大量數(shù)據(jù)(Iterator yield)

codergarden / 2358人閱讀

摘要:開(kāi)發(fā)中經(jīng)常遇到這樣的場(chǎng)景產(chǎn)品汪我要在后臺(tái)做一個(gè)功能,可以導(dǎo)出自定義時(shí)間范圍的訂單信息。結(jié)果,第二天一上班產(chǎn)品汪過(guò)來(lái)就是拍桌子,我想把去年一整年的訂單都導(dǎo)出來(lái),結(jié)果后臺(tái)直接就掛了開(kāi)發(fā)小哥一查,原來(lái)是內(nèi)存溢出了,一年下來(lái)的的訂單量足足有條。

開(kāi)發(fā)中經(jīng)常遇到這樣的場(chǎng)景

產(chǎn)品汪:我要在后臺(tái)做一個(gè)功能,可以導(dǎo)出自定義時(shí)間范圍的訂單信息。開(kāi)發(fā)小哥二話不說(shuō),半天就把功能做完并上線了。結(jié)果,第二天一上班產(chǎn)品汪過(guò)來(lái)就是拍桌子:MD,我想把去年一整年的訂單都導(dǎo)出來(lái),結(jié)果后臺(tái)直接就掛了!

開(kāi)發(fā)小哥一查,原來(lái)是內(nèi)存溢出了,一年下來(lái)的的訂單量足足有1000W條。于是,開(kāi)發(fā)小哥跟產(chǎn)品汪吵了起來(lái):你TM色不色傻,1000W的數(shù)據(jù)你導(dǎo)出來(lái)干diao,你是不是想把服務(wù)器給搞掛掉?

于是,產(chǎn)品汪與程序狗就這么結(jié)下梁子了。

但是。產(chǎn)品的需求你敢這樣懟回去,那如果是老板提的這個(gè)需求呢,就是硬要把1000W條記錄導(dǎo)出來(lái),你還不得乖乖回去碼代碼?

那么,這個(gè)如果真要導(dǎo)出這大量數(shù)據(jù),該怎么做呢?開(kāi)發(fā)中我們經(jīng)常會(huì)使用框架來(lái)提高我們的開(kāi)發(fā)效率,但也意味著框架會(huì)對(duì)一些數(shù)據(jù)進(jìn)行封裝。

比如Yii2,當(dāng)我們想獲取去年一年的訂單時(shí),我們的代碼會(huì)這樣寫:

Order::find()->where("create_time between "2016-01-01" AND "2016-12-31"")->all();

當(dāng)我們將上面代碼得到的結(jié)果集再拿去遍歷時(shí),數(shù)據(jù)量一大,就會(huì)內(nèi)存溢出。
原因是:Yii2中,對(duì)all方法進(jìn)行了封將,將大量的數(shù)據(jù)存入了數(shù)組中,而遍歷大數(shù)據(jù),必然會(huì)導(dǎo)致內(nèi)存迅速上升。
那如何取出大量數(shù)據(jù),而又不存到數(shù)組中呢?這就要用到了PHP中的迭代器:Iterator。如果有看過(guò)PDO::query的返回值類型的話,我們會(huì)發(fā)現(xiàn),這個(gè)方法返回的PDOStatement,正是對(duì)Iterator的實(shí)現(xiàn)。關(guān)于Iterator,請(qǐng)自行腦補(bǔ)。

即然框架幫我們做了多余的封裝,那么我們就改用原生API來(lái)實(shí)現(xiàn)。以下是完整代碼

$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";//設(shè)置文件名
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位數(shù)量級(jí)的記錄,執(zhí)行上面的代碼,通過(guò)查看內(nèi)存使用,發(fā)現(xiàn)整個(gè)過(guò)程只占用了0.XM的內(nèi)存,完全沒(méi)有任何內(nèi)存溢出的現(xiàn)象。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/31623.html

相關(guān)文章

  • PHP利用PDO從mysql讀取大量數(shù)據(jù)處理(可做大量數(shù)據(jù)集的導(dǎo)出,業(yè)務(wù)調(diào)整等)

    摘要:環(huán)境適用場(chǎng)景需要處理一定數(shù)據(jù)集業(yè)務(wù)從讀取一定數(shù)據(jù)的業(yè)務(wù)導(dǎo)出一次需要處理一定的業(yè)務(wù)操作更新刪除等更多需要處理一定數(shù)據(jù)集的操作關(guān)鍵設(shè)置關(guān)鍵設(shè)置,如果不設(shè)置,依舊會(huì)從一次取出數(shù)據(jù)到里的游標(biāo)屬性不是必須的生成器生成器,迭代數(shù)據(jù)操作本生成器可 環(huán)境 mysql: 5.6.34php: 5.6nginx: php-fpm 適用場(chǎng)景 需要處理一定數(shù)據(jù)集業(yè)務(wù) 從mysql讀取一定數(shù)據(jù)的業(yè)務(wù)導(dǎo)出 一次...

    宋華 評(píng)論0 收藏0
  • PHP的生成器

    摘要:它最簡(jiǎn)單的調(diào)用形式看起來(lái)像一個(gè)申明,不同之處在于普通會(huì)返回值并終止函數(shù)的執(zhí)行,而會(huì)返回一個(gè)值給循環(huán)調(diào)用此生成器的代碼并且只是暫停執(zhí)行生成器函數(shù)。 0x01 寫在前面 本文主要介紹: Generator的簡(jiǎn)單用法。 Generator的底層實(shí)現(xiàn)。 本文比較長(zhǎng),可能會(huì)耗費(fèi)你比較多的時(shí)間。如果你比較了解Generator的用法,僅想了解底層實(shí)現(xiàn),可以直接跳到底層實(shí)現(xiàn)部分。 本文分析的PH...

    LMou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<