问题
I'm working on a Laravel 5.2 project and I'm using Eloquent models, but I'm not sure how to approach to aggregation features.
Let's say I have Product and Price models and a hasMany
relationship, so a product can have multiple prices.
Now, in my Product model I'd like a function that will give me an average price of the product.
I found 2 ways to get the same result:
1.) Eloquent aggregation
public function avg_price()
{
return $this->prices()->avg('price');
}
2.) MySql aggregation
public function avg_price()
{
return $this->prices()->groupBy('product_id')->first([\DB::raw('AVG(price) AS avg_price')])->avg_price;
}
So, both of them are showing the right result, however, I'm wondering which one is better to use performance wise.
As far as I understand, Eloquent aggregation would make a collection out of all results (prices) and then calculate the average upon it, and MySQL aggregation would simply do the AVG function in MySQL and return a single row as a result.
I'd like to hear another opinion. Thanks in advance.
回答1:
I cannot make dilemma about these two options. I made a little experiment in this case. Table averager has one column 'value'. The table has 2052195 recorded random integers as well.
$adapter = new mysqli('localhost','korisnik','lozinka','test');
$results = [];
for($i = 1; $i <= 10; $i++){
$start = microtime(true);
$res = $adapter->query("select avg(value) as avg from averager");
$res = $res->fetch_object();
$results['mysql'] = microtime(true)-$start;
$start = microtime(true);
$res = $adapter->query("select * from averager");
$avg = false;
while($resItem = $res->fetch_object())
$avg = $avg ? ($avg+$resItem->value)*0.5 : $resItem->value;
$results['php'] = microtime(true)-$start;
echo "Test number {$i}\r\n";
var_dump($results);
}
Results
Test number 1
array(2) {
'mysql' =>
double(3.6330089569092)
'php' =>
double(15.645164012909)
}
Test number 2
array(2) {
'mysql' =>
double(4.0829129219055)
'php' =>
double(16.118007183075)
}
Test number 3
array(2) {
'mysql' =>
double(3.5810949802399)
'php' =>
double(14.581390857697)
}
Test number 4
array(2) {
'mysql' =>
double(4.1148250102997)
'php' =>
double(15.509108066559)
}
Test number 5
array(2) {
'mysql' =>
double(3.9069290161133)
'php' =>
double(14.851855993271)
}
Test number 6
array(2) {
'mysql' =>
double(3.4348700046539)
'php' =>
double(14.505731105804)
}
Test number 7
array(2) {
'mysql' =>
double(3.589262008667)
'php' =>
double(14.98966383934)
}
Test number 8
array(2) {
'mysql' =>
double(3.6161508560181)
'php' =>
double(15.630507946014)
}
Test number 9
array(2) {
'mysql' =>
double(4.4143221378326)
'php' =>
double(15.816854000092)
}
Test number 10
array(2) {
'mysql' =>
double(4.1319460868835)
'php' =>
double(15.999732017517)
}
来源:https://stackoverflow.com/questions/40852763/eloquent-orm-aggregation-vs-mysql-aggregation