简体   繁体   English

如何优化Laravel雄辩的查询设计和关系?

[英]How to optimize Laravel Eloquent query design and relationships?

I have been trying to learn more about ways to better optimize my eloquent queries. 我一直在尝试学习更多有关如何更好地优化口才查询的方法。 I understand that it involves having more robust database designs and asking data from the server the "right" way. 我了解这涉及进行更可靠的数据库设计,并以“正确”的方式从服务器询问数据。

The Application 应用程序

I have a sample application that lets you add task lists, remove task lists, and edit them (just the title mostly). 我有一个示例应用程序,可让您添加任务列表,删除任务列表并进行编辑(大多数情况下只是标题)。 With each task list, you can add tasks, delete tasks, and edit tasks. 使用每个任务列表,您可以添加任务,删除任务和编辑任务。 A typical CRUD app. 典型的CRUD应用。

在此处输入图片说明

The Code 编码

I wont post my Vue components, unless requested, because I am not sure it's relevant. 除非有要求,否则我不会发布Vue组件,因为我不确定它是否相关。 I am more interested in the initial query optimization. 我对初始查询优化更感兴趣。 I have my relationships setup like this: 我的关系设置如下:

Model: User.php 型号: User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

use App\Models\TaskList;
use App\Task;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'first', 'last', 'email', 'phone', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function lists() {
        return $this->hasMany(TaskList::class,'user_id');
    }
}

Model: TaskList.php 型号: TaskList.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use User;
use App\Models\Task;

class TaskList extends Model
{
    protected $fillable = ['user_id','status','title'];

    public function user() {
        return $this->belongsTo(User::class);
    }

    public function tasks() {
        return $this->hasMany(Task::class,'list_id');
    }

    public function scopeLists() {
        return $this->where('user_id',auth()->user()->id);
    }
}

Model: Task.php 型号: Task.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use App\Models\TaskList;
use App\User;

class Task extends Model
{
    public function list() {
        return $this->belongsTo(TaskList::class);
    }
}

Controller: TaskListController.php @index 控制器: TaskListController.php @index

public function index()
{
    $user = auth()->user()->load('lists.tasks');

    $data = [
        'lists' => $user->lists,
    ];        

    return view('user.tasklist',$data);
}

In my view I am not doing anything special. 我认为我没有做任何特别的事情。 Just sticking my data into my Vues array member lists : 只是将我的数据粘贴到我的Vues数组成员lists

let app = new Vue({
        el: '#app',
        data: {
            lists: []
        }
    });

    @if(isset($lists))
        @foreach($lists as $list)
            app.lists.push({
                id: '{{ $list->id }}',
                title: '{!! addslashes($list->title) !!}',
                status: '{{ $list->status }}',
                tasks: JSON.parse('{!! $list->tasks !!}')
            });
        @endforeach
    @endif

The Problem 问题

The problem is simply that My load time is at about 1 second. 问题很简单,我的加载时间约为1秒。 I have read mixed information online that Laravel is a slow frameworks, others claim they can get sub 20ms load time and so on. 我在网上阅读过混合信息,其中Laravel是一个缓慢的框架,其他人则声称它们可以获得20ms以下的加载时间,依此类推。 Granted, I understand that I am in dev environment and I am going to see different results from production. 当然,我知道我处于开发环境中,并且我将从生产中看到不同的结果。 I also understand that I have dev packages that wouldn't necessarily be loaded in production and that would improve booting. 我也了解我有一些开发软件包,这些软件包不一定会在生产环境中加载,并且可以改善启动。 But I think these numbers below are pretty slow and there's something else going on here. 但是我认为下面的这些数字相当缓慢,这里还有其他情况。

在此处输入图片说明

在此处输入图片说明

The Question 问题

Simply, how can I improve performance and optimize my application in this situation? 简而言之,在这种情况下如何改善性能并优化应用程序?

I want to know what steps I can take in this specific scenario to improve my applications performance. 我想知道在这种特定情况下可以采取哪些步骤来提高应用程序性能。 In my dev box, fully loaded with all my dev packages, I can achieve sub 500ms load times. 在我的开发箱中,已满载所有开发包,我可以达到500毫秒以下的加载时间。 Even 500ms seems slow. 甚至500ms似乎也很慢。 Can Sub 200ms or sub 100ms be achieved? 可以达到200毫秒以下或100毫秒以下吗? Is it just a hardware thing? 仅仅是硬件吗? Or am I totally wrong about my relationships and loading? 还是我对我的人际关系和负担完全错误?

"require": {
    "php": ">=7.1.3",
    "fideloper/proxy": "~4.0",
    "laravel/framework": "5.6.*",
    "laravel/tinker": "~1.0"
},
"require-dev": {
    "barryvdh/laravel-debugbar": "^3.1",
    "filp/whoops": "~2.0",
    "fzaninotto/faker": "~1.4",
    "mockery/mockery": "~1.0",
    "phpunit/phpunit": "~7.0",
    "symfony/thanks": "^1.0"
},

Any insight into optimizing this is greatly appreciated! 非常感谢您对此进行优化的见解!

About your code 关于您的代码

In my knowledge, you are querying your database in the right way, you are using lazy eager loading , that do exactly the same queries that the eager loading do. 据我所知,您正在以正确的方式查询数据库,使用的是懒惰的eager loading ,它执行与eager load完全相同的查询。

You may have some problem on your database. 您的数据库可能有问题。 You did not posted the migrations. 您没有发布迁移。 You must have foreign keys on task_lists.user_id and tasks.list_id referencing to user.id and task_lists.id respectively. 你必须有外键task_lists.user_idtasks.list_id引用到user.idtask_lists.id分别。

Other possible causes 其他可能的原因

  • You are saying that your entire request takes 1s , and are focusing on the queries, but you didn't show the actual query times on Laravel Debugbar. 您说的是整个请求花费1s ,并且专注于查询,但是您没有在Laravel Debugbar上显示实际查询时间。
  • Note that: the booting time is ~600ms and the execution time ~300ms. 请注意:引导时间为〜600ms,执行时间为〜300ms。 Your queries are within the execution time (with many other things). 您的查询在执行时间内(还有很多其他事情)。
  • The booting time is mostly affected by slowness on filesystem access, caused by the common bad guy, the HDD. 引导时间主要受常见的坏蛋HDD导致的文件系统访问缓慢的影响。 Replace by a SSD and you'll notice a high improvement. 替换为SSD,您会发现有很大的改进。
  • Laravel on debug mode with Laravel Debugbar running is significantly slower then on production mode. Laravel在运行Laravel Debugbar的调试模式下比在生产模式下慢得多。 This is because the Database Query Logger is enabled and for other reasons. 这是因为启用了数据库查询记录器以及其他原因。
  • If you have the php xdebug installed, it will also slow down your execution time . 如果您安装了php xdebug,它也会减慢执行时间
  • Remove from Laravel on production everything that you do not use. 在生产中从Laravel删除所有您不使用的东西。 Don't use cookies? 不使用Cookie? Why load CookieServiceProvider ? 为什么要加载CookieServiceProvider Don't use filesystem? 不使用文件系统? Why load FilesystemServiceProvider ? 为什么要加载FilesystemServiceProvider Review your app.providers config. 查看您的app.providers配置。 This will reduce the booting time since you'll load less files. 因为您将加载较少的文件,所以这将减少启动时间。

Okay, fixed all of this, how to improve performance after? 好的,修复所有这些问题之后,如何提高性能?

Assuming that your environment is optimized, your code is optimized, and you still have slow response times, it's time to Profile your code. 假设您的环境进行了优化,代码优化,你仍然有缓慢的响应时间,它的时间来简介你的代码。 With the right profiler tool you will see exactly what piece of code is slowing down. 使用正确的探查器工具,您将确切看到正在减慢的代码段。

If the Database Query itself is slow and there's nothing that you can do to improve, you can use the Laravel's Cache with memcached or redis driver, and cache out your slow queries, so instead of querying the database for the results, they will be on memory and available in microseconds. 如果数据库查询本身很慢,并且您无能为力,您可以使用带有memcached或redis驱动程序的Laravel缓存 ,并缓存掉慢速查询,因此它们将在数据库中查询而不是结果内存,并以微秒为单位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM