<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          php使用yield進行大數據量處理

          共 1788字,需瀏覽 4分鐘

           ·

          2022-08-29 11:54

          目錄  隱藏 

          1 概述

          2 生成器函數

          3 yield關鍵字

          4 一個簡單的例子

          5 遍歷數據庫實例

          5.1 未使用生成器

          5.2 使用生成器

          概述

          當我們需要使用php來處理大數據量時,例如循環(huán)數據庫的所有記錄,這個記錄可能會很大,例如100萬行,那么通過傳統(tǒng)的辦法就行不通了。首先通過web訪問,php有超時時間,默認是30秒。那么就只能通過php cli的方式來執(zhí)行,這樣就沒有超時時間了,但由于數據量太大,php循環(huán)時需要將數據全部載入內存中執(zhí)行,由于數據量太大,php會報Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes)的錯誤。php默認的內存限制為128M,雖然可以通過修改php.ini中memory_limit的選項的值來提高內存限制,但始終不是最優(yōu)的解決辦法。PHP通過生成器函數可以極大節(jié)省內存開銷。

          生成器函數

          生成器函數看起來像普通函數——不同的是普通函數返回一個值,而生成器可以 yield 生成多個想要的值。任何包含 yield 的函數都是一個生成器函數。
          當一個生成器被調用的時候,它返回一個可以被遍歷的對象.當你遍歷這個對象的時候(例如通過一個foreach循環(huán)),PHP 將會在每次需要值的時候調用對象的遍歷方法,并在產生一個值之后保存生成器的狀態(tài),這樣它就可以在需要產生下一個值的時候恢復調用狀態(tài)。

          yield關鍵字

          生成器函數的核心是yield關鍵字。yield關鍵字看起來像一個return申明,不同之處在于普通return會返回值并終止函數的執(zhí)行,而yield會返回一個值給循環(huán)調用此生成器的代碼并且只是暫停執(zhí)行生成器函數。

          一個簡單的例子

          1. <?php

          2. function gen_one_to_three() {

          3. for ($i = 1; $i <= 3; $i++) {

          4. //注意變量$i的值在不同的yield之間是保持傳遞的。

          5. yield $i;

          6. }

          7. }

          8. $generator = gen_one_to_three();

          9. foreach ($generator as $value) {

          10. echo "$value\n";

          11. }

          12. ?>

          以上例子會輸出:

          1. 1

          2. 2

          3. 3

          遍歷數據庫實例

          例如當前我們需要循環(huán)數據庫的emp表,這個表中有100萬行記錄,我們需要循環(huán)并修改mgr的字段的值。

          未使用生成器

          1. $db = sf::getLib('db');

          2. $sql = "select * from emp where mgr = 1 order by id asc";

          3. $query = $db->query($sql);

          4. while ($row = $db->fetch_array($query)) {

          5. $db->exec("update emp set mgr = 2 where id = '{$row['id']}'");

          6. echo "id:" . $row['id'] . "\n";

          7. }

          這在數據量小時并沒有什么問題,但數據量比較大的話,就無法執(zhí)行了,會報內存超過限制的錯誤。

          使用生成器

          1. function test_yield(){

          2. $db = sf::getLib('db');

          3. $sql = "select * from emp where mgr = 1 order by id asc";

          4. $query = $db->query($sql);

          5. while ($row = $db->fetch_array($query)) {

          6. yield $row;

          7. }

          8. }

          9. foreach(test_yield() as $item){

          10. $db->exec("update emp set mgr = 2 where id = '{$row['id']}'");

          11. echo "id:" . $item['id']."\r\n";

          12. }

          通過test_yield這個生成器函數,程序可以正常執(zhí)行,且內存不會超限。


          瀏覽 109
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  香蕉久草 | 国产婷婷色综合AV | 狠狠躁夜夜躁人爽 | 五月婷婷六月婷婷 | 五月天婷婷丁香在线播放 |