雖然 NoSQL 資料庫近年來聲勢大漲,但關聯式資料庫(SQL)依然是主流應用的核心基礎。在翻閱 PHP 官方手冊時,發現 mysqli_query 函數竟支援一個鮮為人知但極具實用價值的參數,能夠控制結果集的獲取模式:
@mysqli_query($this->sql, $SQL, ($method ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT));
根據 PHP 手冊說明,該參數可接受 MYSQLI_USE_RESULT 或 MYSQLI_STORE_RESULT 常數,預設為 MYSQLI_STORE_RESULT。手冊中甚至有開發者留言指出:「若需檢索大量資料,請使用 MYSQLI_USE_RESULT」。這兩種模式的差異究竟有多大?本文將為您深度剖析。
mysqli_fetch_array() 僅從本地緩存中讀取行,永不會發生通訊錯誤;返回 NULL 唯一表示已到達結果集末尾。mysqli_fetch_array() 才從伺服器拉取下一行。mysqli_fetch_array() 返回 NULL 可能表示結果集結束,也可能代表與伺服器通訊發生錯誤,需額外判斷。| 特性 | MYSQLI_STORE_RESULT | MYSQLI_USE_RESULT |
|---|---|---|
| 記憶體需求 | 高(客戶端緩存全量結果) | 低(僅緩存單行) |
| 處理速度 | 較慢(建立複雜結構) | 較快(無結構開銷) |
| 伺服器負載 | 低(查詢後即釋放資源) | 高(長時間鎖定結果集) |
| 適用場景 | 小型結果集、需多次遍歷、隨機存取 | 大型結果集、單向流式處理、記憶體受限環境 |
| 錯誤處理 | 簡單(NULL 僅表示結束) | 複雜(需區分結束與通訊錯誤) |
優先使用 MYSQLI_STORE_RESULT(預設)當:
mysqli_data_seek())考慮 MYSQLI_USE_RESULT 當:
<?php
// 大量資料匯出範例:使用 MYSQLI_USE_RESULT 避免記憶體爆炸
$mysqli = new mysqli("localhost", "user", "password", "database");
$sql = "SELECT * FROM huge_log_table";
if ($result = $mysqli->query($sql, MYSQLI_USE_RESULT)) {
// 設定 HTTP 標頭直接串流下載
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export.csv"');
$out = fopen('php://output', 'w');
fputcsv($out, ['id', 'created_at', 'message']); // 寫入標題
while ($row = $result->fetch_assoc()) {
fputcsv($out, $row); // 逐行寫入,無需載入全部資料
}
fclose($out);
$result->free(); // 釋放結果集,釋放伺服器資源
}
$mysqli->close();
?>
掌握這兩種模式的特性,能讓您在面對不同規模的資料查詢時,做出最佳的效能與資源平衡決策。