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

PHP mysqli_query 緩衝模式差異:MYSQLI_STORE_RESULT vs MYSQLI_USE_RESULT 深度解析

     編輯:PHP 相關知識

核心差異對比

特性MYSQLI_STORE_RESULT (預設)MYSQLI_USE_RESULT
資料傳輸查詢執行後立即將**所有結果集**傳輸到客戶端記憶體查詢執行後**不傳輸資料**,需逐行呼叫 fetch 時才從伺服器讀取
記憶體佔用高(客戶端緩衝整個結果集)低(僅緩衝當前行)
伺服器負載低(釋放伺服器資源快)高(伺服器需維持結果集直到讀完)
fetch 速度極快(從本地記憶體讀取)較慢(每次需網路往返)
錯誤檢測fetch 失敗只會在結束時返回 nullfetch 過程中可能發生網路錯誤
適用場景小~中型結果集、需多次遍歷、隨機存取大型結果集、串流處理、記憶體受限

程式碼示範

緩衝模式 (預設)

$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$result = $mysqli->query('SELECT * FROM large_table'); // 預設 STORE_RESULT

// 此時所有資料已在客戶端記憶體
echo "總筆數: " . $result->num_rows; // 立即可用

while ($row = $result->fetch_assoc()) {
    // 從本地記憶體讀取,極快
    process($row);
}
$result->free(); // 釋放客戶端記憶體

非緩衝模式

$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$result = $mysqli->query('SELECT * FROM huge_table', MYSQLI_USE_RESULT);

// 無法立即取得 num_rows
// $result->num_rows 會報錯或返回 0

while ($row = $result->fetch_assoc()) {
    // 每次從伺服器讀取一行
    process($row);
    
    // 可在處理中決定提前中斷,節省頻寬
    if (shouldStop()) break;
}
// 若中斷讀取,需確保讀完或關閉連線釋放伺服器資源

實務決策指南

function chooseMode($estimatedRows, $avgRowSizeBytes, $memoryLimitMB = 128) {
    $estimatedMemory = $estimatedRows * $avgRowSizeBytes;
    $memoryLimit = $memoryLimitMB * 1024 * 1024 * 0.7; // 留 30% 給其他

    if ($estimatedMemory < $memoryLimit) {
        return MYSQLI_STORE_RESULT; // 安全,效能佳
    }
    return MYSQLI_USE_RESULT; // 節省記憶體
}

// 使用範例
$mode = chooseMode(100000, 500); // 10萬筆,平均500 bytes ≈ 50MB
$result = $mysqli->query($sql, $mode);

進階:分批處理大量資料

function processInChunks($mysqli, $sql, $chunkSize = 1000) {
    $offset = 0;
    do {
        $chunkSql = "$sql LIMIT $offset, $chunkSize";
        $result = $mysqli->query($chunkSql, MYSQLI_STORE_RESULT);
        
        $count = 0;
        while ($row = $result->fetch_assoc()) {
            process($row);
            $count++;
        }
        $result->free();
        $offset += $chunkSize;
    } while ($count === $chunkSize);
}

常見誤區

  • 誤以為 USE_RESULT 更快:單行 fetch 確實較慢,但避免了大量記憶體分配,整體視情況而定
  • USE_RESULT 時使用 num_rows:會導致錯誤,必須改用 SELECT COUNT(*) 另行查詢
  • 未釋放結果集:STORE_RESULT 必須呼叫 free(),USE_RESULT 需讀完或關閉連線
  • 在 USE_RESULT 期間執行其他查詢:會導致「Commands out of sync」錯誤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved