编程

优化 Laravel 站点的 5 个小技巧

395 2023-05-30 12:05:00

没有什么比一个需要时间加载的网站更令人沮丧的了。如果这种情况发生在你的用户身上,他们会在你有机会说服他们之前离开你的网站。

以下是一些加快 Laravel 网站和应用的小技巧。

1. 查看慢查询

查看为每个页面请求所运行的所有查询的一个简单方法是安装 Laravel Debugbar。

Laravel Debugbar 让你可以深入每个查询,查看绑定并查看哪些查询超出了必要时间。

如果查询需要花费很长时间。检查其查询的表是否定义了必要的索引。可以通过数据库迁移调用 ->index($columnName) 方法将索引添加到列中。

public function up()
{
    Schema::table('posts', function (Blueprint $table) {
    	$table->index('author_id');
    });
}

要检查查询是否命中索引,在 SQL 工具中运行查询之前,复制该 SQL 并将 EXPLAIN 前置到查询语句中。这将告诉您查询是否使用索引。

如果没看到 ”Using index condition",那么这就是为查询的字段添加索引的提示,否则就重写查询或完全放弃它。

2. 缓存

缓存是一种可以应用于不需要返回最新实时数据的各种操作的技术。无论是 API 请求还是慢查询,在前面抛出缓存都会导致很大的不同。

在 Laravel 中,我们可以永远缓存结果,也可以在再次执行操作之前缓存一段时间。

例如:永久缓存可以通过 Cache Facade 来实现。

use Illuminate\Support\Facades\Cache;

...

// Cache forever until busted
$subscriptionPlans = Cache::rememberForever('subscription_plans', function () {
    return SubscriptionPlan::query()
        ->orderBy('price')
        ->get()
        ->groupBy('name');
});

// Bust the cache
Cache::forget('subscription_plans');

再比如,在清除缓存并重新生成值之前缓存 2 天。

use Illuminate\Support\Facades\Cache;
use Carbon\CarbonInterval;

...

// Cache value for 2 days
$subscriptionPlans = Cache::remember('subscription_plans', CarbonInterval::days(2), function () {
    return SubscriptionPlan::query()
        ->orderBy('price')
        ->get()
        ->groupBy('name');
});

考虑将此技术用于用户频繁点击的耗时查询。COUNT 查询是一个很好的开始,如果用在有大量行的表上,它可以使数据库瘫痪。

3. 在查询中只 Select 你需要的数据

当通过数据库填充模型时,除非您另有说明,否则 Eloquent 将执行 SELECT* 查询以从数据库中检索所有行。这通常不是问题,直到你开始拉取,比如说 1000 行,每个行有 200 个字段,而你所需要的只是一个标题。

所有这些操作都给数据库带来了不必要的压力,随之而来的是,网络现在必须传输比必要的更多的数据。

为了缓解这种情况。调用 Eloquent 生成器时,请使用 select() 方法指定所需的列。

$subscriptionPlans = SubscriptionPlan::query()
    ->select(['id', 'name', 'price'])
    ->get();

如果你只需要单个值,那么可以通过 ->value($column)->pluck($column) 获取。

// Return the name of the first matching row
$subscriptionPlans = SubscriptionPlan::query()
    ->value('name'); // returns 'Free'

$subscriptionPlans = SubscriptionPlan::query()
    ->pluck('name'); // returns an array (collection) of all matching rows with 'name' as the value.

4. 预先加载

预加载解决了新开发人员在开始使用 Laravel 时通常面临的最常见、最容易解决的问题之一。

 N+1 问题是,我们为循环遍历的每个模型调用一个额外的查询。例如,当循环浏览用户列表时,我们可能还想显示另一个表中的相关数据。

它可能看起来像这样:

$users = User::query()
    ->take(10)
    ->get(); // 1 Query

foreach ($users as $user) {
    // +1 query every iteration, when accessing the user invoice relationship.
    echo $user->name . ' paid at: ' . $user->invoice->paid_at . PHP_EOL;
}

上面的例子假设我们查询 10 个用户会执行 11 个查询。

使用预加载,无论检索多少用户都能减少到 2 个查询。

$users = User::query()
    ->with('invoice')
    ->take(10)
    ->get();
    
...

或者在之后加载:

$users = User::query()
    ->take(10)
    ->get();
        
$users->load('invoice');

...

5. 也可能只是你的服务器问题

看看你的 PHP 版本,你可以使用的服务器规格,以及你当前的主机是否物有所值。你的网站可能会受到过时硬件的阻碍。如果这是你遇到的情况,可以去了解一下不同服务器商的一些实例。

如果您想将数据库分离到自己的资源中,很多主机商也提供托管数据库实例。不过,这确实需要额外的费用。

结论

如果想了解更多 Laravel 的网站优化相关的问题,查看下面相关推荐的一些文章。