Laravel Оптимизация запросов (SQL) - PullRequest
0 голосов
/ 13 января 2020

Моя 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 для конкретной школы. Скажем, school_id = 3, я выбираю всех пользователей и связанные с ними уровни, а затем увеличиваю значение уровня на 1 для этих пользователей (F становится 1, 12+ удаляется, а все остальные числа увеличиваются на 1).

Когда я использую al oop до l oop через пользователей, сопоставляю их user_id и затем обновляю запись, это будут тысячи запросов. Это замедляет работу всего приложения, а также приводит к созданию sh.

Одной идеальной вещью будут 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;

Я все еще ищу другие возможные варианты.

Ответы [ 2 ]

0 голосов
/ 13 января 2020

Существует множество способов оптимизации запроса, которые перечислены ниже:

=> В этой ситуации вам лучше использовать Cache, и вам не нужно каждый раз обращаться к базе данных. Это может сократить время обработки и повысить производительность.

=> Индексирование различных таблиц позволило сократить время до 10 секунд, что опять-таки слишком долго

=> Вы также можете использовать select в запросе, что сокращает время выборки всех данных столбцов

0 голосов
/ 13 января 2020

Сначала определил отношение в вашей модели, например:

В модели 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...