PHP大量資料迴圈時記憶體耗盡問題的解決方案
最近在開發一個PHP程式時遇到了下面的錯誤:
PHP Fatal error: Allowed memory size of 268 435 456 bytes exhausted
錯誤資訊顯示允許的最大記憶體已經耗盡。遇到這樣的錯誤起初讓我很詫異,但轉眼一想,也不奇怪,因為我正在開發的這個程式是要用一個foreach
迴圈語句在一個有4萬條記錄的表裡全表搜尋具有特定特徵的資料,也就是說,一次要把4萬條資料取出,然後逐條檢查每天資料。可想而知,4萬條資料全部載入到記憶體中,記憶體不爆才怪。
畢竟程式設計這麼多年,我隱約記得PHP裡提供有非一次全部載入資料的API,是像處理流媒體那樣,隨用隨取隨丟、資料並不會積累在記憶體的查詢方法。經過簡單的搜尋,果然在官方網站上找到的正確的用法。
這個問題在PHP的官方網站上叫緩衝查詢和非緩衝查詢(Buffered and Unbuffered queries)。 PHP的查詢預設模式是緩衝模式。也就是說,查詢資料結果會一次全部提取到記憶體裡供PHP程式處理。這樣給了PHP程式額外的功能,比如說,計算行數,將 指標指向某一行等。更重要的是程式可以對資料集反覆進行二次查詢和過濾等操作。但這種緩衝查詢模式的缺陷就是消耗記憶體,也就是用空間換速度。
相對的,另外一種PHP查詢模式是非緩衝查詢,資料庫伺服器會一條一條的返回資料,而不是一次全部返回,這樣的結果就是PHP程式消耗較少的記憶體,但卻增加了資料庫伺服器的壓力,因為資料庫會一直等待PHP來取資料,一直到資料全部取完。
很顯然,緩衝查詢模式適用於小資料量查詢,而非緩衝查詢適應於大資料量查詢。
對於PHP的緩衝模式查詢大家都知道,下面列舉的例子是如何執行非緩衝查詢API。
非緩衝查詢方法一: mysqli
<?php $mysqli = new mysqli("localhost", "my_user", "my_password", "world"); $uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT); if ($uresult) { while ($row = $uresult->fetch_assoc()) { echo $row['Name'] . PHP_EOL; } } $uresult->close(); ?>
非緩衝查詢方法二: pdo_mysql
<?php $pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass'); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $uresult = $pdo->query("SELECT Name FROM City"); if ($uresult) { while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) { echo $row['Name'] . PHP_EOL; } } ?>
非緩衝查詢方法三: mysql
<?php $conn = mysql_connect("localhost", "my_user", "my_pass"); $db = mysql_select_db("world"); $uresult = mysql_unbuffered_query("SELECT Name FROM City"); if ($uresult) { while ($row = mysql_fetch_assoc($uresult)) { echo $row['Name'] . PHP_EOL; } } ?>
相關文章
- 如何解決PHP裡大量資料迴圈時記憶體耗盡的問題PHP記憶體
- Linux下php-fpm程式過多導致記憶體耗盡問題解決LinuxPHP記憶體
- kswapd 耗盡系統記憶體 kscand 耗盡系統cpu的解決記憶體
- 解決 SQL Server 耗盡記憶體的情況SQLServer記憶體
- 避免PHP-FPM記憶體洩漏導致記憶體耗盡PHP記憶體
- 共享記憶體段未釋放導致資料庫記憶體被耗盡記憶體資料庫
- 耗盡實體記憶體觀查swap記憶體
- 淺談 ABAP 程式執行時出現『記憶體耗盡』錯誤的問題試讀版記憶體
- 在PHP中怎麼解決大量資料處理的問題PHP
- react 記憶體洩露常見問題解決方案React記憶體洩露
- 處理大型資料集而不會耗盡記憶體的方式推薦記憶體
- phpexcel 處理大量資料時記憶體溢位PHPExcel記憶體溢位
- UIWebView與tableView巢狀的記憶體問題及解決方案UIWebView巢狀記憶體
- 解決golang 的記憶體碎片問題Golang記憶體
- 記憶體耗盡後Redis會發生什麼記憶體Redis
- 解決SQL Server資料庫佔用記憶體過多的問題SQLServer資料庫記憶體
- 【騰訊開源】iOS爆記憶體問題解決方案-OOMDetector元件iOS記憶體OOM元件
- Oracle核心資料庫由於大量的latch free導致CPU資源耗盡的現場解決過程Oracle資料庫
- 解決git記憶體洩露問題Git記憶體洩露
- vertica記憶體不足的解決方案記憶體
- 為硬體保留記憶體 問題的解決方法記憶體
- 告別記憶體OOM,解決MySQL記憶體增長問題記憶體OOMMySql
- 解決Apache長時間佔用記憶體大的問題,Apache 記憶體優化方法Apache記憶體優化
- Python中處理大型資料集而不會耗盡記憶體的方式推薦Python記憶體
- 難解決的記憶體洩露(OutOfMemory)問題!!!記憶體洩露
- java向excel 寫入海量資料記憶體溢位問題 解決JavaExcel記憶體溢位
- 如何在 iOS 中解決迴圈引用的問題iOS
- Composer 記憶體不足解決方案 PHP Fatal error: Out of memory記憶體PHPError
- 故障分析 | MySQL 耗盡主機記憶體一例分析MySql記憶體
- 解決ListView1的介面資料與記憶體不一致問題,將記憶體資料更新到介面上View記憶體
- ARC記憶體管理以及迴圈引用記憶體
- Josephus問題解決方法四(迴圈陣列)陣列
- iOS UIWebView記憶體暴漲問題的解決方法iOSUIWebView記憶體
- 解決Windows下棧記憶體過小的問題Windows記憶體
- 【虹科乾貨】使用記憶體資料庫解決三個資料庫效能問題記憶體資料庫
- 解決NSTimer迴圈引用導致記憶體洩漏的六種方法記憶體
- 關於PHP記憶體洩漏的問題PHP記憶體
- sybase中cursor的使用中死迴圈問題解決