例如從兩張表中分別查出上百萬條資料,現在需要把這些資料群組裝在一起然後在插入到另外一張表中,請問除了使用數組組裝外還能怎麼處理,如果使用數組的話怎麼才能保證不超出記憶體限制。
回複內容:
例如從兩張表中分別查出上百萬條資料,現在需要把這些資料群組裝在一起然後在插入到另外一張表中,請問除了使用數組組裝外還能怎麼處理,如果使用數組的話怎麼才能保證不超出記憶體限制。
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中使用協程實現多任務調度
保證不記憶體溢出的方法很簡單,最佳化演算法,分批次逐步完成任務,減少每次讀出資料的數量。
一點一點的寫