Maka saya punya kejutan untuk Anda - Ini adalah tes kinerja kecil:
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
adalah tabel dengan hanya satu kolom int dan 1 juta baris.
Dan Hasilnya adalah:
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
Jadi "dampak kinerja kecil dari fasih" adalah:
- Hampir 20 kali lebih lambat daripada menggunakan PDO biasa dan
stdClass
saat mengambil data dari database. - Setidaknya 100 kali lebih lambat dari
stdClass
saat membaca properti/atribut dalam satu lingkaran.
Jadi, jika Anda ingin meningkatkan kinerja, beralihlah ke PDO biasa saat menangani data dalam jumlah besar atau setidaknya gunakan Builder default.
Sekarang Anda masih dapat mencoba melakukan pekerjaan di MySQL, tetapi persyaratan untuk menggunakan Eloquent tidak masuk akal.
Namun Anda dapat mencoba versi campuran - Gunakan Eloquent untuk membuat kueri, tetapi ubah menjadi Database\Query\Builder
dengan getQuery()
.
$fooBars = FooBar::where('type', 'FOO')->orderBy('id')
->getQuery()
->select(['*', DB::raw('coalesce(`value` - @last, 0)'), DB::raw('@last := `value`')])
->get();
Tetapi saya akan selalu menghindari penggunaan variabel sesi dengan cara ini dalam kode aplikasi, karena saya telah melihat banyak solusi seperti itu mengembalikan hasil yang salah/tidak terduga setelah peningkatan versi.
Masih belum yakin? Berikut adalah beberapa tes lainnya:
Menggunakan variabel sesi dalam kueri Eloquent yang dikonversi ke Database\Query\Builder
:
$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
Solusi PHP menggunakan kueri Eloquent yang dikonversi:
$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
Solusi PHP dengan PDO biasa dan stdClass
$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
Solusi PHP dengan PDO biasa dan array asosiatif:
$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
Solusi pilihan Anda adalah yang paling lambat dan paling tidak dapat diandalkan. Jadi jawaban atas pertanyaan Anda adalah solusi yang buruk untuk masalah Anda.