Laravel 数据库性能优化实战(一):测量数据库性能指标
前面学院君通过 32 篇教程的篇幅,从 Server 端整体架构到 InnoDB 索引、事务以及数据库高可用性四个方面给大家整体介绍了高性能 MySQL 的理论基础,接下来,我们以 Laravel 项目为例,通过几个实例给大家演示下如何在具体项目中优化 MySQL 的查询性能。
Laravel Debugbar
MySQL 查询性能优化指标主要有两个:一个是内存使用,一个是查询耗时。工欲善其事,必先利其器,在进行 Laravel 项目开发时,我们可以使用 Laravel Debugbar 这个扩展包在本地调试时实时查看当前页面数据库内存使用情况和每条 SQL 语句的查询耗时。
你可以通过如下 Composer 指令在 Laravel 项目根目录下安装这个扩展包:
composer require barryvdh/laravel-debugbar --dev
安装完成后,就可以在本地开发环境浏览该 Laravel 应用页面时,在页面底部看到对应的调试工具条了(5.5之前的版本需要手动注册对应的服务提供者方可看到):
数据库性能相关指标
你可以通过「Quries」标签页查看该页面涉及到的所有数据库查询语句:
以及单条语句和所有语句的查询/更新耗时,工具条顶部的内存使用和请求耗时是页面整体的内存使用和处理耗时,数据库内存使用和查询耗时只是其中一部分。所以通过这里我们可以精确定位数据库查询耗时情况。
要想精确定位数据库内存使用情况,如果使用了 Eloquent 模型类的话,可以通过「Models」标签页查看。
我们通过 Laravel 自带的模型工厂创建 10000 个测试用户:
User::factory()->count(10000)->create();
然后在首页路由处理器中通过用户名获取指定用户:
Route::get('/', function () {
$user = \App\Models\User::where('name', '柳红')->first();
return view('welcome', ['user' => $user]);
});
这样,刷新应用首页,就可以在 Debugbar 调试工具条中看到「Models」标签页有数据了:
当然,这也是比较粗粒度的统计模型实例的数量,后面介绍关联查询的时候会详细介绍如何通过优化获取模型实例的数量降低数据库查询内存使用率。
通过添加索引优化查询性能
现在使用的查询列 name
上尚未设置任何索引,所以通过 name
进行等值查询实际上会进行一次全表扫描(下图是通过 explain 分析执行计划):
好在整体数据量不大,所以即便是全表扫描,也不会造成慢查询。
我们尝试给整个字段加上索引:
php artisan make:migration alter_users_add_name_index --table=users
给新增的迁移类编写索引设置代码:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AlterUsersAddNameIndex extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->index('name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropIndex('name');
});
}
}
然后运行迁移命令让其生效:
php artisan migrate
刷新应用首页,在「Queries」标签页可以看到查询时间大幅缩短,users
表的数据量越大,优化越明显:
因为这个时候,可以基于 B+ 树索引快速定位到对应的记录:
只需要扫描 1 行,而没有使用索引的时候,扫描了 9999 行。
2 Comments
扫描了9969行,哈哈
只是预估的行数