[PHP7]PDOのfetchモード速度比較

# 検証内容

PHP7へと環境を刷新しているので、職場のMySQL5.7に入ってた6500件ほどのデータを使って検証。
前もってselectをしておいたのでMySQLのバッファに全データが乗っているはず。
検索結果を全行返却する処理を5000回試行して、かかった平均・合計時間を計測した。

# ソースコード（テーブル定義だけ伏せたやつ）

```php
<?php
$pdo = new PDO('mysql:host=localhost;dbname=hoge_db', 'root', 'pass');

// 性能検証用の処理
function profile($text, $f) {
        $testCount = 5000; // 試行回数
        $totalTime = .0;
        for($i = 0; $i < $testCount; ++$i){
                $start = microtime(true);
                $rows = $f();
                $end = microtime(true);
                $time = $end - $start;
                $totalTime += $time;
        }
        $avg = $totalTime / $i;
        printf("$text [ avg ] %1.6f [total] %3.6f \n", $avg, $totalTime);
}

// fetchで利用するテーブルマッピング用のクラス
class FetchClass {
        public $pk_1;    // int
        public $pk_2;    // int
        public $param_1; // int
        public $param_2; // int
        public $param_3; // int
        public $param_4; // int
        public $timestamp_1; // timestamp
        public $timestamp_2; // timestamp
}

// 1 : 行単位読み取り + 連想配列で受け取るモード
profile("fetch    ASSOC", function() use ($pdo) {
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_ASSOC);
        $st->execute();
        $rows = [];
        while($row = $st->fetch()){
                $rows[] = $row;
        }
        return $rows;
});

// 2 : 行単位読み取り + stdClassで受け取るモード
profile("fetch    OBJ  ", function() use ($pdo) {
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_OBJ);
        $st->execute();
        $rows = [];
        while($row = $st->fetch()){
                $rows[] = $row;
        }
        return $rows;
});

// 3 : 行単位読み取り + 指定クラスで受け取るモード（各行を新規インスタンス生成）
profile("fetch    CLASS", function() use ($pdo){
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_CLASS, 'FetchClass');
        $st->execute();
        $rows = [];
        while($row = $st->fetch()){
                $rows[] = $row;
        }
        return $rows;
});

// 4 : 行単位読み取り + 指定クラスで受け取るモード（各行を既存インスタンスへ貼り付け）
profile("fetch    INTO ", function() use ($pdo){
        $st = $pdo->prepare('select * from hoge_table');
        $fetchCls = new FetchClass;
        $st->setFetchMode(PDO::FETCH_INTO, $fetchCls);
        $st->execute();
        $rows = [];
        while($row = $st->fetch()){
                // 他と同じ結果となるようクローンして格納
　　　　　　　　　// ここで処理して編集した結果を返すなら違う結果になるかも
                $rows[] = clone $row;
        }
        return $rows;
});

// 5 : 全行一括読み取り + 連想配列で受け取るモード
profile("fetchAll ASSOC", function() use ($pdo) {
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_ASSOC);
        $st->execute();
        $rows = $st->fetchAll();
        return $rows;
});

// 6 : 全行一括読み取り + stdClassで受け取るモード
profile("fetchAll OBJ  ", function() use ($pdo) {
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_OBJ);
        $st->execute();
        $rows = $st->fetchAll();
        return $rows;
});

// 7 : 全行一括読み取り + 連想配列で受け取るモード（各行を新規インスタンス生成）
profile("fetchall CLASS", function() use ($pdo){
        $st = $pdo->prepare('select * from hoge_table');
        $st->setFetchMode(PDO::FETCH_CLASS, 'FetchClass');
        $st->execute();
        $rows = $st->fetchAll();
        return $rows;
});

// 8 : fetchAllで既存インスタンスを使いまわすFETCH_INTOは不可能なので計測なし
```

# 結果

|No|処理|返却方法|平均(秒)|合計(秒)||倍率(切り上げ)|
|--:|:--|:--|--:|--:|:--|--:|
|1|fetch    ASSOC|連想配列|0.015279|76.392952|最速|1倍(基準)|
|2|fetch    OBJ  |stdClass|0.016582|82.908913|遅い|1.09倍|
|3|fetch    CLASS|指定クラス(newする)|0.016311|81.553230|遅い|1.07倍|
|4|fetch    INTO |指定クラス(既存インスタンス)|0.015970|79.849632|中間|1.05倍|

|No|処理|返却方法|平均(秒)|合計(秒)||倍率(切り上げ)|
|--:|:--|:--|:----:|--:|:--|--:|
|5|fetchAll ASSOC|連想配列|0.011633|58.164605|最速|1倍(基準)|
|6|fetchAll OBJ  |stdClass|0.012816|64.082171|遅い|1.10倍|
|7|fetchall CLASS|指定クラス(newする)|0.012597|62.984455|遅い|1.09倍|

> 連想配列(ASSOC) > 指定クラス(INTO) > 指定クラス(CLASS) == stdClass(OBJ)

この順番で早かったです。
あと全行返却するならfetchAllを使うこと。