Laravel:如何优化多个查询

Posted

技术标签:

【中文标题】Laravel:如何优化多个查询【英文标题】:Laravel: How to optimize multiple queries 【发布时间】:2017-11-02 06:11:55 【问题描述】:

对 HomeController 文件的查询会降低网站速度。页面完全加载需要 20 秒。 (页面大小仅为 3.9 Mb,每次加载页面时 CPU 负载都会上升 80%)。我被告知使用比 Elequant 更快的查询生成器并加入查询以将它们作为一个查询发送。我觉得这太难了。我在哪里可以看到一些例子?

家庭控制器

public function index()

    $sliders = Post::where('post_type','slider')
        ->with('FeaturedImage','PostField')
        ->orderBy('created_at', 'desc')
        ->limit(4)
        ->get();

    $page1 = Post::where([
        ['post_type','=','custom_page'],
        ['slug','=','page1'],
    ])
        ->with('FeaturedImage','PostField')
        ->latest()
        ->first();


    $page2 = Post::where([
        ['post_type','=','custom_page'],
        ['slug','=','page2'],
    ])
        ->with('FeaturedImage','PostField')
        ->latest()
        ->first();


    $page3 = Post::where([
        ['post_type','=','custom_page'],
        ['slug','=','page-3'],
    ])
        ->with('FeaturedImage','PostField')
        ->latest()
        ->first();


    $compacts = array(
        'sliders',
        'page1',
        'page2',
        'page3',
    );
    return view('site.home')->with(compact($compacts));

编辑: 迁移后

public function up()

    // Create table for storing roles
    Schema::create('posts', function (Blueprint $table) 
        $table->increments('id');
        $table->integer('author_id');
        $table->integer('category_id')->nullable();
        $table->string('title');
        $table->text('excerpt')->nullable();
        $table->text('body')->nullable();
        $table->string('slug')->nullable();//unique()
        $table->string('post_type')->default('post');
        $table->enum('status', ['PUBLISHED', 'DRAFT', 'PENDING'])->default('DRAFT');
        $table->timestamps();
    );

【问题讨论】:

我在哪里可以看到一些例子?你试过谷歌吗? laravel 文档? 你基本上是无缘无故地执行了 3 次查询 如何将此查询合并为一个查询? 你能展示你的帖子表的迁移吗? @patricus 是的,我更新了 【参考方案1】:

您正在对 posts 表运行四个查询,但它们都没有使用索引。这意味着对帖子表进行四次全表扫描。此外,您正在对非索引字段进行排序。这也可能导致性能问题。

您需要在post_typeslug 上为您的查询条件建立一个索引。您可以创建两个单独的索引,也可以创建一个复合索引。这取决于您的应用需求。

$table->string('slug')->nullable()->index();
$table->string('post_type')->default('post')->index();

【讨论】:

【参考方案2】:

你可能想做这样的事情来获取所有页面,然后使用集合groupBy()函数拆分页面

Post::where('post_type','=','custom_page')
->whereIn('slug',['page1','page2','page-3'])
->whereRaw('id IN (select MAX(id) FROM post GROUP BY slug)')
->with('FeaturedImage','PostField')
->get()
->groupBy('slug');

【讨论】:

以上是关于Laravel:如何优化多个查询的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 查询中使用多个 OR、AND 条件

如何在 laravel eloquent 中查询多个关系

如何使用 Laravel 查询构建器跨表选择多个列?

如何在 laravel eloquent 中组合这些多个查询

如何使用 Laravel Eloquent 创建多个 Where 子句查询?

如何使用 Laravel Eloquent 创建多个 Where 子句查询?