Php 如何在Laravel雄辩的便捷附件上提高数据库性能?
因此,Laravel的Php 如何在Laravel雄辩的便捷附件上提高数据库性能?,php,mysql,laravel,laravel-5,eloquent,Php,Mysql,Laravel,Laravel 5,Eloquent,因此,Laravel的$appends是一个非常好的特性。我有一个产品表,我在$appends数组中添加了供应商、图像和其他内容,因此我的代码如下所示: 类产品扩展\ResourceModel{ protected $appends = ['vendor', 'images']; function getVendorAttribute() { return $this->vendor()->first(); } function getImages() { $th
$appends
是一个非常好的特性。我有一个产品
表,我在$appends
数组中添加了供应商
、图像
和其他内容,因此我的代码如下所示:
类产品扩展\ResourceModel{
protected $appends = ['vendor', 'images'];
function getVendorAttribute() {
return $this->vendor()->first();
}
function getImages() {
$this->_images = $this->images()->get();
}
整洁,嗯
但是,并非如此,下面是这段整洁的代码正在执行的查询列表:
select * from `products`;
select * from `images` where `images`.`imageable_id` = 1 and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` = 1;
select * from `images` where `images`.`imageable_id` = 2 and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` = 2;
select * from `images` where `images`.`imageable_id` = 3 and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` = 3;
select * from `images` where `images`.`imageable_id` = 4 and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` = 4;
select * from `images` where `images`.`imageable_id` = 5 and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` = 5;
当然,我宁愿做:
select * from `products`;
select * from `images` where `images`.`imageable_id` in (1, 2, 3, 4, 5) and `images`.`imageable_type` = 'Product';
select * from `vendors` where `vendors`.`id` in(1, 2, 3, 4, 5);
甚至是连接
等效项
因此,我的详细问题如下:
1) 我在20页中加载产品。这会生成大约41个查询(实际上,为了这个问题,我对其进行了简化)。我认为这真的会损害性能,对吗?对于一个平均的MySQL盒,第一种类型的41个简单查询确实比第二种类型的3个查询更耗时
2) 在我疯狂修复所有应用程序逻辑之前,是否有一种捆绑(或打包,或简单)的方式在Laravel上实现这一点
提前感谢!您应该立即加载查询并将访问器修改为以下内容:
function getVendorFirstAttribute() {
$vendors = $this->vendor;
return $vendors->shift();
}
function getImagesAllAttribute() {
return $this->images;
}
问题在于,您的方法正在使用关系查询,因此每次访问它们时,它们都会运行一个新的查询,并且没有利用任何延迟或急切的加载 您可以通过确保急切地加载关系并访问方法中的关系属性(
$this->vendor
vs$this->vendor()
)来解决此问题,但您需要重命名getVendorAttribute()
方法,以便它不会与关系属性冲突
但是,我认为您可能要查找的是模型上的$with
属性。如果您在模型上设置$with
属性,则属性列出的关系将始终渴望加载该模型。此外,由于这些关系将始终存在,因此当模型转换时,它们将始终存在ted添加到数组中,无需向$appends
属性添加任何内容
所以,你的班级看起来像:
class Product extends Model {
// always eager load the vendor and images relationships
protected $with = ['vendor', 'images'];
// relationship to the vendor
public function vendor()
{
return $this->belongsTo(Vendor::class);
}
// relationship to the images
public function images()
{
return $this->hasMany(Image::class);
}
}
在上面的类中,如果要在已加载的产品
实例上调用toArray()
或toJson()
,则输出将包括相关的供应商
和相关的图像
对于额外的阅读,我建议阅读和。Laravel的附录不够聪明,无法做到开箱即用。您可以使用
查询范围自己创建此功能。
。事实上,我永远不会向根据任何类型的查询构建的模型添加任何内容。只有格式化程序等。您的getVendorAttribute()
方法将覆盖供应商
关系属性,在方法内调用$this->vendor
将导致“未定义属性”错误。此外,关于关系属性,$this->vendor
将已经包含相关的供应商记录,并调用first()
,它将实际运行一个新的查询并返回数据库中的第一个供应商记录。