php - Laravel 查询优化 (SQL)
问题描述
我的user_level
数据库结构是
| user_id | level |
| 3 | F |
| 4 | 13 |
| 21 | 2 |
| 24 | 2 |
| 33 | 3 |
| 34 | 12+ |
我还有一张桌子users
| id | school_id |
| 3 | 3 |
| 4 | 4 |
| 21 | 2 |
| 24 | 2 |
| 33 | 3 |
| 34 | 1 |
我必须实现的是,我必须level
根据某个预定义的条件更新每个用户的。但是,我的users
表真的很大,有数千条记录。
有一次,我只更新user_level
特定学校的记录。说for school_id = 3
,我获取所有用户及其关联的级别,然后将这些用户的级别值增加1(F变为1,12+被删除,所有其他数字都增加1)。
当我使用循环遍历用户,匹配他们user_id
然后更新记录时,将有数千个查询。这会减慢整个应用程序的速度并导致它崩溃。
一个理想的事情是 laravel 交易,但我怀疑它是否优化了时间。我在一个包含大约 6000 条记录的简单查询中对其进行了测试,它运行良好。但由于某种原因,它与我拥有的记录并没有那么好。
只是看一些关于任何其他查询优化技术的建议。
更新
我实现了一个解决方案,我将根据级别(使用 laravel 集合)对所有记录进行分组,然后与现在的数百/数千个相比,我只需发出 13 个更新查询。
$students = Users::where('school_id', 21)->get();
$groupedStudents = $students->groupBy('level');
foreach ($groupedStudents as $key => $value) :
$studentIDs = $value->pluck('id');
// condition to check and get the new value to update
// i have used switch cases to identify what the next level should be ($NexLevel)
UserLevel::whereIn('userId', $studentIDs)->update(["level" => $nextLevel]);
endforeach;
我仍在寻找其他可能的选择。
解决方案
首先在您的模型中定义一个关系,例如:
在 UserLevel 模型中:
public function user() {
return $this->belongsTo(\App\UserLevel::class);
}
并且您可以仅通过一个查询更新level
没有 12+ 级别的查询,并通过一个查询删除所有 12+ 级别。
UserLevel::where('level', '<=', 12)->whereHas('user', function($user) {
$user->where('school_id', 3);
})->update(['level' => DB::raw("IF(level = 'F', 1, level+1)")]);
UserLevel::whereHas('user', function($user) {
$user->where('school_id', 3);
})->where('level', '>', 12)->delete();
如果您的数据太大。您还可以使用chunk
拆分它们以减少内存消耗。
像这样:
UserLevel::where('level', '<=', 12)->whereHas('user', function($user) {
$user->where('school_id', 3);
})->chunk(5000, function($user_levels) {
$user_levels->update(['level' => DB::raw("IF(level = 'F', 1, level+1)")]);
});
UserLevel::whereHas('user', function($user) {
$user->where('school_id', 3);
})->where('level', '>', 12)->delete();
推荐阅读
- c# - 如何在运行时获取数字基元数据类型的字节大小、MinValue、MaxValue
- html - 出现在输入元素中的随机样式。它来自哪里?
- python - 如何使用 python 中的正则表达式从以下字符串中获取值
- python - 计算 Pandas 的每月异常值
- cucumber - BeforeStep AfterStep 不被调用
- security - Apache Kafka 是否支持 LDAP,或者它是一个 Confluent 功能?
- docker - 我的弹性 beanstalk docker 部署的应用程序的 API 网关
- vba - 如何使 VBA 代码突出显示为 word 中的跟踪修订?
- python - 在主脚本中调用外部 python 脚本并在那里运行
- java - 如何使用模数来选择通过 Java 中的 100 个循环迭代的 4 个语句?