mysql - Eloquent 使用远程 MySQL DB 花费的时间太长

标签 mysql laravel rest amazon-web-services eloquent

我正在开发一个 Web (Laravel) 和 iOS 应用程序,它们都使用我也在使用 Laravel 开发的 REST API。来自托管在 AWS RDS 实例上的 MySQL 数据库的 API 查询。

当我在本地主机上同时设置 API 和应用程序,并将 API 配置为连接我的本地数据库(与应用程序和 API 在同一台机器上)时,它按预期工作正常,但问题出在我设置 API 时从 AWS RDS 数据库而不是本地查询。 用 Eloquent 方式进行简单的查询,比如

Product::where('brand_id', '=', $id)
               ->get()

大约需要 10 - 15 分钟才能完成,但是如果我使用查询生成器执行相同的查询,例如;

DB::select('select * from products where brand_id = ?', [$id]);

工作正常。

直接在 MySQL 上执行查询或在 Laravel Tinker 上运行 Product::all() 可以按预期使用本地 API/远程数据库设置。

编辑:

这是我执行 SHOW CREATE TABLE products 时得到的结果

CREATE TABLE `products` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `SKU` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `price` double(8,2) NOT NULL,
  `description` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `product_details` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `material_and_care` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `material` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `care` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `colors` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `made_in` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `size_chart` text COLLATE utf8mb4_unicode_ci,
  `size_chart_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `brand_id` int(10) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `published` tinyint(1) NOT NULL DEFAULT '0',
  `featured` tinyint(1) NOT NULL DEFAULT '0',
  `promo_title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `promo_caption` text COLLATE utf8mb4_unicode_ci NOT NULL,
  `shipping_height` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `shipping_width` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `shipping_length` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `shipping_weight` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `is_vertical` tinyint(1) NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `products_category_id_foreign` (`category_id`),
  KEY `products_brand_id_foreign` (`brand_id`),
  CONSTRAINT `products_brand_id_foreign` FOREIGN KEY (`brand_id`) REFERENCES `brands` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `products_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `subcategories` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=501 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

我的产品型号:

class Product extends Model
{
    use SoftDeletes, CascadeSoftDeletes;

    protected $cascadeDeletes = [
        'items',
        'options',
        'images',
        'sizes'
    ];

    protected $fillable = [
        'sku',
        'name',
        'price',
        'description',
        'product_details',
        'material_and_care',
        'material',
        'color_1',
        'color_2',
        'color_3',
        'care',
        'made_in',
        'size_chart',
        'size_chart_url',
        'brand_id',
        'category_id',
        'published',
        'featured',
        'promo_title',
        'promo_caption',
        'shipping_weight',
        'shipping_height',
        'shipping_width',
        'shipping_length',
        'is_vertical'
    ];

    protected $appends = [
        'interests',
        'brand',
        'options',
        'sizes',
        'items',
        'images',
        'comment_count',
        'discount',
        'suits_me_count'
    ];

    protected $hidden = [
        'created_at',
        'deleted_at',
        'updated_at',
        'subcategory'
    ];

    protected static function boot()
    {
        parent::boot();
        static::addGlobalScope(new PublishedProductScope);
    }

    public function getDiscountAttribute() {
        return $this->discount()->first();
    }

    public function getSuitsMeCountAttribute() {
        return $this->suitsmes()->count();
    }

    public function getCommentCountAttribute() {
        return $this->comments()->count();
    }


    public function getImagesAttribute(){
        return $this->images()->pluck("url");
    }

    public function getInterestsAttribute() {
        return $this->interests()->get();
    }

    public function getBrandAttribute(){
        return $this->brand()->first();
    }

    public function getOptionsAttribute(){
        return $this->options()->get();
    }

    public function getSizesAttribute(){
        return $this->sizes()->get();
    }

    public function getItemsAttribute(){
        return $this->items()->get();
    }

    public function interests() {
        return $this->belongsToMany('App\Interest', 'product_interest');
    }

    public function brand() {
        return $this->belongsTo('App\Brand');
    }

    public function options() {
        return $this->hasMany('App\ProductOption');
    }

    public function sizes() {
        return $this->hasMany('App\ProductSize');
    }

    public function items() {
        return $this->hasMany('App\ProductItem');
    }

    public function images() {
        return $this->hasMany('App\ProductImage');
    }

    public function comments() {
        return $this->hasMany('App\ProductComment');
    }

    public function suitsmes() {
        return $this->belongsToMany('App\User', 'wishlist', 'product_id', 'user_id');
    }

    public function discount(){
        return $this->hasOne('App\Discount');
    }

    public function category() {
        return $this->belongsTo('App\Subcategory', 'category_id');
    }

}

还有我的品牌模型:

class Brand extends Model
{


 protected $fillable = [
        'first_name',
        'last_name',
        'email',
        'phone_number',
        'birth_date',
        'ssn',
        'street_address',
        'street_address_2',
        'city_address',
        'state_address',
        'postal_code_address',
        'legal_name',
        'dba',
        'tax_id',
        'street_business_address',
        'street_business_address_2',
        'city_business_address',
        'state_business_address',
        'postal_code_business_address',
        'destination_fund',
        'email_business',
        'phone_number_business',
        'account_number_fund',
        'routing_number_fund'
    ];

    protected $hidden = [
        'created_at',
        'deleted_at',
        'updated_at'
    ];

    protected $appends = [
        'images'
    ];

    public function getImagesAttribute()
    {
        return $this->images()->get();
    }

    public function getBillboardPicturesAttribute() {
        $pictures = [$this->billboard, $this->billboard2, $this->billboard3, $this->billboard4];
        return $pictures;
    }    

    public function users()
    {
        return $this->belongsToMany('App\User', 'user_brand_role', 'brand_id', 'user_id');
    }

    public function getInterestsAttribute() {
        return $this->interests()->pluck('interest_id');
    }

    public function interests() {
        return $this->belongsToMany('App\Interest', 'brand_interest', 'brand_id', 'interest_id');
    }

    public function products() {
        return $this->hasMany('App\Product');
    }

    public function images() {
        return $this->hasMany('App\BrandImage');
    }

    public function categories() {
        return $this->hasMany('App\Category');
    }

    public function getCatalogAttribute() {
        return $this->categories()->orderBy('name', 'asc')->get();
    }


}

最佳答案

问题是您的 Product 模型中的这段代码:

protected $appends = [
    'interests',
    'brand',
    'options',
    'sizes',
    'items',
    'images',
    'comment_count',
    'discount',
    'suits_me_count'
];

These properties are relationships, and so they result in multiple joins every time Eloquent reads/returns a row.

此查询:DB::select('select * from products where brand_id = ?', [$id]); 不会导致任何连接,并且是来自单个的选择查询 table 。这就是为什么当您比较结果时,您会发现查询时间存在巨大差异。

有两种可能的解决方案:

<强>1。删除附加内容

删除附加项,每当您需要关系时使用 with 函数

<强>2。隐藏附加属性

您可以将此代码添加到您的Product 模型中:

protected $hidden = [
    'created_at',
    'deleted_at',
    'updated_at',
    'interests',
    'brand',
    'options',
    'sizes',
    'items',
    'images',
    'comment_count',
    'discount',
    'suits_me_count'
];

当您需要属性时,只需使用 $product->makeVisible('property_name')。否则,默认情况下不会加载或查询这些属性

关于mysql - Eloquent 使用远程 MySQL DB 花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48814659/

相关文章:

Mysql 查询计数或家长记录

java - Hibernate Criteria 限制字段命名困惑

php - Laravel 队列 - 如何设置 FAST 处理器

php - 从 Laravel 访问查询字符串值

node.js - 如何流式传输 API 响应而不是将其全部加载到 RAM 中

java - Apache Camel 根据请求使用文件内容丰富消息

php - mysql 日期格式与 jquery 日期格式不工作

java - 是否有 MySQL 的 Spring Batch 3 升级脚本?

php - 有什么方法可以在 Laravel 的 .css 文件中使用 Blade 来生成 "CSS" View ?

rest - 基于 If-Modified-Since header 修改 REST API 表示是否有效?