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

PHP MySQL 緩衝查詢 vs 非緩衝查詢深度解析:mysqli、PDO 實務選擇指南

     編輯:PHP 綜合知識

核心差異

特性緩衝查詢非緩衝查詢
記憶體佔用PHP 進程一次性載入全部結果集MySQL 端保留,PHP 逐行取回
結果集導航可隨意移動指標(data_seek、num_rows)僅能順向讀取(fetch)
並發限制查詢結束即釋放伺服器資源未讀完前無法在同連線發送新查詢
適用場景結果集較小、需隨機存取、需知筆數大結果集、串流處理、記憶體受限

mysqli 介面

// 緩衝(預設)
$res = $mysqli->query("SELECT * FROM huge_table"); // MYSQLI_STORE_RESULT
$res = $mysqli->query("SELECT * FROM huge_table", MYSQLI_STORE_RESULT);
$stmt->store_result(); // 預處理語句轉緩衝

// 非緩衝
$res = $mysqli->query("SELECT * FROM huge_table", MYSQLI_USE_RESULT);
$res = $mysqli->use_result();
// 預處理預設即為非緩衝,需呼叫 store_result() 轉緩衝

PDO 介面

// 緩衝(預設)
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$res = $pdo->query("SELECT * FROM huge_table");

// 非緩衝
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$res = $pdo->query("SELECT * FROM huge_table");
// 非緩衝下 $res 是 PDOStatement,需 fetch() 逐行

記憶體考量:libmysqlclient vs mysqlnd

  • libmysqlclient:結果集記憶體在 C 層,memory_limit 不計入,直到賦值給 PHP 變數
  • mysqlnd (PHP 5.4+ 預設):結果集記憶體在 PHP 記憶體管理內,memory_limit 可正確限制

預處理語句特殊行為

$stmt = $mysqli->prepare("SELECT * FROM logs WHERE level = ?");
$stmt->bind_param('s', $level);
$stmt->execute();

// 預設非緩衝:結果留在 MySQL,fetch() 逐行取回
// 需知總筆數或隨機存取時:
$stmt->store_result(); // 一次性拉回 PHP
echo $stmt->num_rows;  // 此時可用

// 用完釋放
$stmt->free_result();

// 取得結果集物件(需 mysqlnd)
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);

選擇決策樹

  1. 結果集 < 10MB 且需 num_rows/隨機存取 → 緩衝
  2. 結果集巨大(GB 級)、串流處理(CSV 匯出、ETL)、記憶體受限 → 非緩衝
  3. 非緩衝模式下:必須 讀完所有行或呼叫 free_result() 才能在同連線執行下一條 SQL
  4. 長時間運行腳本(Worker、CLI)偏好非緩衝 + 批次處理,避免記憶體洩漏

效能觀測建議

  • 啟用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 捕獲錯誤
  • 使用 memory_get_peak_usage(true) 監控 PHP 記憶體峰值
  • MySQL 端 SHOW PROCESSLIST 觀察 Sending data 狀態持續時間
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved