首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 大量資料查詢記憶體優化:從 mysql_query 到 PDO 無緩衝模式

     編輯:PHP 綜合知識

PHP 處理百萬級資料集的記憶體突破方案

當使用 mysql_query 或 PDO 預設模式查詢超大結果集時,常遇到 Allowed memory size exhausted 致命錯誤。本文深入分析原因,並提供 PDO 無緩衝查詢的完整解決方案。

問題根源分析

傳統 mysql_query 與 PDO 預設行為皆為緩衝查詢:一次性將所有結果集載入記憶體。當資料量達到千萬筆,記憶體佔用呈指數級增長,輕易突破 memory_limit 限制。

解決方案:無緩衝查詢

MySQL 提供 mysql_unbuffered_query,PDO 對應 PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false。核心差異:

特性緩衝查詢無緩衝查詢
記憶體佔用載入全部結果集逐行處理,記憶體恆定
資料列計數支援 num_rows不支援
同一連線並發支援多查詢需處理完或重新連線
適用場景小/中型結果集大數據匯出、ETL、報表產生

實戰程式碼對比

緩衝模式(記憶體爆炸)

function selectBuffered() {
    $pdo = new PDO("mysql:host=localhost;dbname=test", 'root', '123456');
    $sth = $pdo->prepare('SELECT * FROM large_table');
    $sth->execute();
    
    echo '初始記憶體:' . memory_get_usage() . "\n";
    while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
        // 處理邏輯
    }
    // 記憶體持續飆升,最終 OOM
}

無緩衝模式(記憶體穩定)

function selectUnbuffered() {
    $pdo = new PDO("mysql:host=localhost;dbname=test", 'root', '123456');
    // 關鍵設定:停用緩衝
    $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
    
    $sth = $pdo->prepare('SELECT * FROM large_table');
    $sth->execute();
    
    echo '初始記憶體:' . memory_get_usage() . "\n";
    while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
        // 記憶體維持在 145KB 左右,極度穩定
        processRow($row);
    }
}

實測數據對比(千萬筆測試表)

  • 緩衝模式:執行 execute() 瞬間記憶體飆升至 200MB+,拋出 Fatal error: Allowed memory size of 134217728 bytes exhausted
  • 無緩衝模式:全程記憶體穩定在 145KB 左右,成功處理完畢

注意事項與替代方案

  1. 游標限制:無緩衡查詢期間,同一連線無法執行其他查詢
  2. 分頁替代:使用 LIMIT offset, count 分批處理,兼顧記憶體與並發
  3. 生成器模式:PHP 5.5+ 可封裝為 Generator,語意更清晰
  4. MySQL 8.0+:支援側邊查詢,進一步優化大數據掃描

掌握無緩衝查詢技巧,讓 PHP 輕鬆應對百萬級甚至億級資料處理任務,不再受限於記憶體瓶頸。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved