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

PHP 查詢 MySQL 四種獲取結果集方法效能對比與選型指南

     編輯:MySQL 綜合教學

PHP 舊版 mysql_* 擴展(已棄用,僅供維護舊專案參考)提供四種獲取結果集方法。本文對比其效能、回傳結構、適用場景,並給出現代 PDO/MySQLi 的對應最佳實踐。

四種方法對比 (mysql_* 時代)

方法回傳結構效能排名特點適用場景
mysql_result()單一標量值最慢 (1x 基準)隨機存取任意行/欄,每次呼叫內部 seek極少量資料、特定單值提取
mysql_fetch_row()數值索引陣列 [0,1,2]最快 (~1.2x)僅數值索引,記憶體最省高效能、不需欄位名、固定欄位順序
mysql_fetch_array()雙模式 [0=>val, 'col'=>val]快 (~1.25x)預設 MYSQL_BOTH,可指定 MYSQL_NUM/MYSQL_ASSOC最常用,兼顧可讀性與效能
mysql_fetch_object()物件 $row->col較慢 (~1.4x)面向物件風格,屬性名=欄位名OOP 專案、結構複雜、需封裝邏輯

實測代碼框架


$link = mysql_connect('localhost', 'root', 'root');
mysql_select_db('test');
mysql_query('SET NAMES utf8');

$sql = "SELECT * FROM large_table LIMIT 100000";
$res = mysql_query($sql);

// 1. mysql_result
$start = microtime(true);
while ($row = mysql_fetch_row($res)) { /* ... */ }
echo "fetch_row: " . (microtime(true) - $start);

// 2. mysql_fetch_array
mysql_data_seek($res, 0);
$start = microtime(true);
while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) { /* ... */ }
echo "fetch_array: " . (microtime(true) - $start);

// 3. mysql_fetch_object
mysql_data_seek($res, 0);
$start = microtime(true);
while ($row = mysql_fetch_object($res)) { /* ... */ }
echo "fetch_object: " . (microtime(true) - $start);

現代最佳實踐:PDO / MySQLi

mysql_* 擴展自 PHP 7.0 移除,新專案必須使用 PDO 或 MySQLi。

PDO::FETCH 模式對應

mysql_* 方法PDO 對應MySQLi 對應
mysql_fetch_row()PDO::FETCH_NUMmysqli_fetch_row()
mysql_fetch_array(MYSQL_ASSOC)PDO::FETCH_ASSOCmysqli_fetch_assoc()
mysql_fetch_array(MYSQL_BOTH)PDO::FETCH_BOTH (預設)mysqli_fetch_array(MYSQLI_BOTH)
mysql_fetch_object()PDO::FETCH_OBJ / FETCH_CLASSmysqli_fetch_object()

PDO 推薦寫法


$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,  // 預設關聯陣列
    PDO::ATTR_EMULATE_PREPARES => false,
]);

$stmt = $pdo->query("SELECT id, name, email FROM users LIMIT 100000");
foreach ($stmt as $row) {
    // $row = ['id'=>1, 'name'=>'John', 'email'=>'john@example.com']
    // 直接用欄位名存取,可讀性最佳
    process($row['name'], $row['email']);
}

// 大資料集分批處理 (生成器模式)
function fetchBatch(PDO $pdo, string $sql, int $batch = 1000): Generator {
    $stmt = $pdo->query($sql);
    $batchData = [];
    foreach ($stmt as $row) {
        $batchData[] = $row;
        if (count($batchData) >= $batch) {
            yield $batchData;
            $batchData = [];
        }
    }
    if ($batchData) yield $batchData;
}

foreach (fetchBatch($pdo, "SELECT * FROM logs") as $batch) {
    processBatch($batch);  // 記憶體穩定
}

選型決策樹

  1. 新專案:PDO + FETCH_ASSOC,預設模式,可讀性最佳、支援預處理、跨資料庫。
  2. 極致效能/記憶體敏感:PDO::FETCH_NUM / mysqli_fetch_row(),搭配生成器分批。
  3. OOP 風格/實體映射:PDO::FETCH_CLASS 映射到 Entity 類別,或 FETCH_OBJ。
  4. 維護舊專案:理解上述四種差異,逐步重構為 PDO。

核心建議

  • 預設用 FETCH_ASSOC:欄位名自文檔化,重構安全,效能差異微乎其微(<5%)。
  • 避免 mysql_result():隨機存取極慢,已被淘汰。
  • 大結果集必須分批:生成器/游標避免記憶體爆炸。
  • 預處理語句:防注入、執行計畫複用,PDO/MySQLi 核心優勢。

方法選擇不應只看微基準測試,而應以代碼可維護性、安全性、記憶體穩定性為首要考量。PDO::FETCH_ASSOC 是 95% 場景的最優解。

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