简体   繁体   English

Laravel 查询优化 (SQL)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM