优化 Laravel 站点的 5 个小技巧
没有什么比一个需要时间加载的网站更令人沮丧的了。如果这种情况发生在你的用户身上,他们会在你有机会说服他们之前离开你的网站。
以下是一些加快 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 的网站优化相关的问题,查看下面相关推荐的一些文章。