それから私はあなたに驚きを持っています-ここに小さなパフォーマンステストがあります:
class Seq extends Eloquent {
protected $table = 'helper.seq';
protected $primaryKey = 'i';
}
Route::get('/loop', function () {
$limit = 10000;
$st = microtime(true);
$data = Seq::orderBy('i')->take($limit)->get();
var_dump(microtime(true) - $st);
$st = microtime(true);
foreach ($data as $row) {
$row->i;
}
var_dump(microtime(true) - $st);
$pdo = DB::getPdo();
$st = microtime(true);
$data2 = $pdo
->query("select * from helper.seq order by i limit $limit")
->fetchAll(PDO::FETCH_OBJ);
var_dump(microtime(true) - $st);
$st = microtime(true);
foreach ($data2 as $k => $row) {
if ($k == 0) {
$row->diff = 0;
} else {
$row->diff = $row->i - $data2[$k-1]->i;
}
}
var_dump(microtime(true) - $st);
});
helper.seq
は、int列が1つと行が100万行しかないテーブルです。
結果は次のとおりです。
0.779045s <- Fetch from DB with Eloquent
1.022058s <- Read Eloquent data (Only one column and do nothing with it)
0.020002s <- Fetch from DB with PDO
0.009999s <- Calculate all diffs in a loop
したがって、「雄弁なパフォーマンスへの小さな影響」は次のとおりです。
- プレーンPDOと
stdClass
を使用するよりも約20倍遅くなります データベースからデータをフェッチするとき。 -
stdClass
より少なくとも100倍遅い ループ内のプロパティ/属性を読み取るとき。
したがって、パフォーマンスを向上させたい場合は、大量のデータを処理するときにプレーンPDOに切り替えるか、少なくともデフォルトのビルダーを使用してください。
これで、MySQLでその仕事を試すことができますが、Eloquentを使用するという要件は意味を成しません。
ただし、混合バージョンを試すことはできます-Eloquentを使用してクエリを作成しますが、それをDatabase\Query\Builder
に変換します getQuery()
を使用 。
$fooBars = FooBar::where('type', 'FOO')->orderBy('id')
->getQuery()
->select(['*', DB::raw('coalesce(`value` - @last, 0)'), DB::raw('@last := `value`')])
->get();
しかし、バージョンのアップグレード後にそのようなソリューションの多くが間違った/予期しない結果を返すのを見たので、アプリケーションコードでこのようにセッション変数を使用することは常に避けます。
まだ納得できませんか?その他のテストは次のとおりです。
Database\Query\Builder
に変換されたEloquentクエリでのセッション変数の使用 :
$st = microtime(true);
$data = Seq::getQuery()
->select(['*', DB::raw('coalesce(i - @last, 0)'), DB::raw('@last := i')])
->orderBy('i')->take($limit)->get();
var_dump(microtime(true) - $st);
// runtime: 0.045002s
変換されたEloquentクエリを使用したPHPソリューション:
$st = microtime(true);
$data2 = Seq::getQuery()->orderBy('i')->take($limit)->get();
foreach ($data2 as $k => $row) {
if ($k == 0) {
$row->diff = 0;
} else {
$row->diff = $row->i - $data2[$k-1]->i;
}
}
var_dump(microtime(true) - $st);
// runtime: 0.039002
プレーンPDOとstdClass
を使用したPHPソリューション
$st = microtime(true);
$data3 = $pdo
->query("select * from helper.seq s1 order by i limit $limit")
->fetchAll(PDO::FETCH_OBJ);
foreach ($data3 as $k => $row) {
if ($k == 0) {
$row->diff = 0;
} else {
$row->diff = $row->i - $data3[$k-1]->i;
}
}
var_dump(microtime(true) - $st);
// runtime: 0.035001s
プレーンなPDOと連想配列を使用したPHPソリューション:
$st = microtime(true);
$data4 = $pdo
->query("select * from helper.seq s1 order by i limit $limit")
->fetchAll(PDO::FETCH_ASSOC);
foreach ($data4 as $k => $row) {
if ($k == 0) {
$row['diff'] = 0;
} else {
$row['diff'] = $row['i'] - $data4[$k-1]['i'];
}
}
var_dump(microtime(true) - $st);
// runtime: 0.027001s
推奨されるソリューションは、最も低速で信頼性が最も低いソリューションです。したがって、あなたの質問に対する答えは、あなたの問題に対する悪い解決策です。