PHP處理大量資料的問題

來源:互聯網
上載者:User
例如從兩張表中分別查出上百萬條資料,現在需要把這些資料群組裝在一起然後在插入到另外一張表中,請問除了使用數組組裝外還能怎麼處理,如果使用數組的話怎麼才能保證不超出記憶體限制。

回複內容:

例如從兩張表中分別查出上百萬條資料,現在需要把這些資料群組裝在一起然後在插入到另外一張表中,請問除了使用數組組裝外還能怎麼處理,如果使用數組的話怎麼才能保證不超出記憶體限制。

mysql_query函數查詢的方式是查詢出全部結果後緩衝到記憶體中,這樣就會出現超記憶體的現象,使用另外一個函數mysql_unbuffered_query可以解決這個問題,mysql_unbuffered_query不會緩衝結果集,而是查詢出來資料後立馬對結果集進行操作,也就是便查詢邊返回,這樣就不會出現超出記憶體的現象,但是使用mysql_unbuffered_query的是時候不能使用 mysql_num_rows() 和 mysql_data_seek()。並且向 MySQL 發送一條新的 SQL 查詢之前,必須提取掉所有未緩衝的 SQL 查詢所產生的結果行。例如:

使用緩衝結果集的代碼:

function selecttest()    {        try {            $pdo = new PDO("mysql:host=localhost;dbname=test", 'root', '123456');//            不使用緩衝結果集方式//            $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);            $sth = $pdo->prepare('select * from test');            $sth->execute();            echo '最初佔用記憶體大小:' . memory_get_usage() . "\n";            $i = 0;            while ($result = $sth->fetch(PDO::FETCH_ASSOC)) {                $i += 1;                if ($i > 10) {                    break;                }                sleep(1);                print_r($result);                echo '佔用記憶體大小:' . memory_get_usage() . "\n";            }        } catch (Exception $e) {            echo $e->getMessage();        }    }

執行時將會報超出記憶體的錯誤:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 204800000 bytes) in E:\ProgramDevelopment\RuntimeEnvironment\xampp\htdocs\test\test.php on line 56Call Stack:    0.0005     135392   1. {main}() E:\ProgramDevelopment\RuntimeEnvironment\xampp\htdocs\test\test.php:0    0.0005     135568   2. test->selecttest() E:\ProgramDevelopment\RuntimeEnvironment\xampp\htdocs\test\test.php:85    0.0050     142528   3. PDOStatement->execute() E:\ProgramDevelopment\RuntimeEnvironment\xampp\htdocs\test\test.php:56

將上面代碼中的$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);一行的注釋去掉後將不在緩衝結果集,這時運行該函數的結果如下:

最初佔用記憶體大小:144808Array(    [id] => 1    [a] => v    [b] => w    [c] => i)佔用記憶體大小:145544Array(    [id] => 2    [a] => b    [b] => l    [c] => q)佔用記憶體大小:145544Array(    [id] => 3    [a] => m    [b] => p    [c] => h)佔用記憶體大小:145536Array(    [id] => 4    [a] => j    [b] => i    [c] => b)佔用記憶體大小:145536

可以看到,這時返回一條資料記憶體佔用非常的小,也就700多位元組,這樣就不會出現超出記憶體的錯誤了。

使用數組...一起載入進記憶體...呵呵呵...肯定很難受的~

解決辦法就是PHP的新特性...額,其實不是很新了。

迭代產生器,(迭代)產生器也是一個函數,不同的是這個函數的傳回值是依次返回,而不是只返回一個單獨的值.或者,換句話說,產生器使你能更方便的實現了迭代器介面.下面通過實現一個xrange函數來簡單說明:

上面這個xrange()函數提供了和PHP的內建函數range()一樣的功能.但是不同的是range()函數返回的是一個包含值從1到100萬0的數組(註:請查看手冊). 而xrange()函數返回的是依次輸出這些值的一個迭代器, 而不會真正以數組形式返回.

這種方法的優點是顯而易見的.它可以讓你在處理大資料集合的時候不用一次性的載入到記憶體中.甚至你可以處理無限大的資料流.

當然,也可以不同通過產生器來實現這個功能,而是可以通過繼承Iterator介面實現.但通過使用產生器實現起來會更方便,不用再去實現iterator介面中的5個方法了.

建議參考鳥哥的一片文章: 在PHP中使用協程實現多任務調度

保證不記憶體溢出的方法很簡單,最佳化演算法,分批次逐步完成任務,減少每次讀出資料的數量。

一點一點的寫

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.