[英]Laravel Query Optimization (SQL)
My user_level
database structure is我的user_level
数据库结构是
| user_id | level |
| 3 | F |
| 4 | 13 |
| 21 | 2 |
| 24 | 2 |
| 33 | 3 |
| 34 | 12+ |
I have another table users
我有另一个表users
| id | school_id |
| 3 | 3 |
| 4 | 4 |
| 21 | 2 |
| 24 | 2 |
| 33 | 3 |
| 34 | 1 |
What I have to achieve is that, I will have to update the level
of each user based on a certain predefined condition.我必须实现的是,我必须根据某个预定义条件更新每个用户的level
。 However, my users
table is really huge with thousands of records.但是,我的users
表真的很大,有数千条记录。
At one instance, I only update the user_level
records for a particular school.有一次,我只更新特定学校的user_level
记录。 Say for school_id = 3
, I fetch all the users and their associated levels, and then increase the value of level by 1 for those users (F becomes 1, 12+ is deleted, and all other numbers are increased by 1).假设school_id = 3
,我获取所有用户及其关联级别,然后将这些用户的级别值增加 1(F 变为 1,删除 12+,所有其他数字增加 1)。
When I use a loop to loop through the users, match their user_id
and then update the record, it will be thousands of queries.当我使用循环遍历用户,匹配他们的user_id
然后更新记录时,这将是数千个查询。 That is slowing down the entire application as well as causing it to crash.这会减慢整个应用程序的速度并导致它崩溃。
One ideal thing would be laravel transactions, but I have doubts if it optimises the time.一个理想的事情是 laravel 事务,但我怀疑它是否优化了时间。 I tested it in a simple query with around 6000 records, and it was working fine.我在一个包含大约 6000 条记录的简单查询中对其进行了测试,并且运行良好。 But for some reason, it doesnt work that good with the records that I have.但出于某种原因,它对我拥有的记录并没有那么好。
Just looking some recommendation on any other query optimization techniques.只是寻找有关任何其他查询优化技术的一些建议。
UPDATE更新
I implemented a solution, where I would group all the records based on the level (using laravel collections), and then I would only have to issue 13 update queries as compared to hundreds/thousands now.我实现了一个解决方案,我将根据级别(使用 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;
I am still looking for other possible options.我仍在寻找其他可能的选择。
First defined a relationship in your model, like:首先在您的模型中定义一个关系,例如:
In UserLevel model:在用户级别模型中:
public function user() {
return $this->belongsTo(\App\UserLevel::class);
}
And you can just update the level
without 12+ level's query, only by one query , and delete all 12+ level by one query .并且您可以只更新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();
If your datas is too huge.如果你的数据太大。 you can also use chunk
to split them for reduce memory consumption.您还可以使用chunk
来拆分它们以减少内存消耗。
like this:像这样:
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();
There are many ways to optimise query which are as below:有多种优化查询的方法,如下所示:
=> At this situation, you better use Cache and doesn't need to hit the database for every time. =>在这种情况下,最好使用 Cache 并且不需要每次都访问数据库。 It can reduce the processing time and have better performance.它可以减少处理时间并具有更好的性能。
=> Indexing various tables, this brought the time down to 10 seconds, again far too long =>索引各种表,这将时间缩短到 10 秒,同样太长了
=> You can also use select
in query which reduces the time to fetch all columns data =>您还可以在查询中使用select
以减少获取所有列数据的时间
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.