Помогите пожалуйста, очень медленно работает при нагрузке в 70 человек с обновлением раз в 5 сек обрабатывается секунд 10-15 PHP: public function show(Request $request, $id) { $user = \Auth::user(); $tournament = \Cache::remember('Tournament@show_' . $id, 5, function () use ($id) { return Tournament::select($this->select)->find($id); }); $round = $request->get('round') ? $request->get('round') : $tournament->round; $grids = TGrids::select('*') ->where('tournament_id', $tournament->id) ->with(['matches' => function ($query) { $query->select(['grid_id', 'tournament_id', 'status', 'win', 'code']); }]); $TPlayersSelect = [ 'tournaments_players.user_id', 'tournaments_players.role', 'round', 'team', 'nickname', 'avatar', 'exp', 'users.role AS site_role', 'grid_id' ]; if (\Perm::allows('tournament@info-role')) if (\Perm::role(['moder', 'admin', 'dev'])) $TPlayersSelect = array_merge($TPlayersSelect, ['note']); $players = TPlayers::select($TPlayersSelect) ->where('tournaments_players.tournament_id', $id) ->join('users', 'users.id', '=', 'tournaments_players.user_id') ->join('games_accounts', 'games_accounts.id', '=', 'tournaments_players.account_id') ->with([ 'profile' => function ($query) use ($tournament) { $profileSelects = ['user_id', 'game', 'mmr']; if (\Perm::allows('tournament@info-role')) if (\Perm::role(['moder', 'admin', 'dev'])) $profileSelects = array_merge($profileSelects, ['priority', 'roles']); $query->select($profileSelects); $query->where('game', $tournament->game); }, 'statistics' => function ($query) use ($tournament) { $query->select('user_id', 'win', 'lose'); $query->where(DB::raw('DATE_FORMAT(created_at , \'%Y-%m\')'), date('Y-m')); $query->where('game', $tournament->game); $query->where('type', $tournament->type); } ]); if ($request->get('round') != 'all') { $grids->where('round', $round); $players->where('tournaments_players.round', $round); } $name = '_t' . $tournament->id . '_r' . $round . '_u-r' . $user->role; $players = \Cache::remember('TPlayers' . $name, 5, function () use ($players) { return $players->get(); }); if ($tournament->grid_disable) { $grids = []; $players = $players->map(function ($player, $key) { $player->team = null; $player->role = null; return $player; }); } else { $grids = \Cache::remember('TGrids' . $name, 5, function () use ($grids) { return $grids->get(); }); if (\Perm::allows('tournament@edit', $tournament)) { $grids->each(function ($grid, $k) { $grid->matches->makeVisible(['code']); }); } else { $player = $players->where('user_id', $user->id) ->where('round', $tournament->round)->first(); if ($player && $player->grid_id) { $grid = $grids->where('id', $player->grid_id)->first(); if ($grid) $grid->matches->makeVisible(['code']); } } } $tournament->players = $players; $tournament->grids = $grids; return $tournament; } PHP: class TGrids extends Model { protected $table = 'tournaments_grids'; public $timestamps = false; protected $fillable = [ 'tournament_id', 'round', 'grid', 'bo', 'win', 'team1', 'team2', 'team1_score', 'team2_score' ]; } PHP: class TMatches extends Model { protected $table = 'tournaments_matches'; protected $fillable = [ 'tournament_id', 'grid_id', 'status', 'win', 'code', 'match' ]; protected $hidden = ['code']; } PHP: class Tournament extends Model { protected $fillable = [ 'user_id', 'provider_id', 'name', 'img', 'desc', 'prize', 'twitch', 'discord', 'game', 'type', 'round', 'lvl', 'max_players', 'leave_disable', 'grid_disable', 'start', 'status' ]; protected $casts = [ 'leave_disable' => 'boolean', 'grid_disable' => 'boolean' ]; } PHP: class GameProfile extends Model { protected $table = 'games_profiles'; protected $fillable = [ 'user_id', 'game', 'mmr', 'priority', 'roles' ]; protected $casts = [ 'roles' => 'array', 'mmr' => Rang::class ]; } PHP: class GameAccount extends Model { protected $table = 'games_accounts'; protected $fillable = [ 'user_id', 'game','nickname', 'profileId', 'accountId', 'active' ]; } PHP: class TStatistics extends Model { protected $table = 'tournaments_statistics'; protected $fillable = [ 'user_id', 'points', 'game', 'type', 'win', 'lose', 'k', 'd', 'a' ]; } PHP: class Rang implements CastsAttributes { /** * Cast the given value. * * @param \Illuminate\Database\Eloquent\Model $model * @param string $key * @param mixed $value * @param array $attributes * @return mixed */ public function get($model, $key, $value, $attributes) { $league = null; $division = null; foreach (config('games.lol.leagues') as $league_key => $divisions) { $divisions_key = array_reverse(array_keys($divisions)); foreach ($divisions_key as $division_key) { $elo = $divisions[$division_key]; if ($value >= $elo) { $league = $league_key; $division = count($divisions_key) > 1 ? $division_key : null; } else return [ 'league' => $league, 'division' => $division ]; } } return [ 'league' => $league, 'division' => $division ]; } } PHP: return [ 'lol' => [ 'leagues' => [ 'iron' => [1 => 400, 2 => 300, 3 => 200, 4 => 100], 'bronze' => [1 => 800, 2 => 700, 3 => 600, 4 => 500], 'silver' => [1 => 1200, 2 => 1100, 3 => 1000, 4 => 900], 'gold' => [1 => 1600, 2 => 1500, 3 => 1400, 4 => 1300], 'platinum' => [1 => 2000, 2 => 1900, 3 => 1800, 4 => 1700], 'diamond' => [1 => 2400, 2 => 2300, 3 => 2200, 4 => 2100], 'master' => [1 => 2500], 'grandmaster' => [1 => 2600], 'challenger' => [1 => 2700] ] ] ];
Реально ли заменит короткие опросы на уведомления по веб-сокету? --- Добавлено --- Индексы в базе продуманы, поставлены? --- Добавлено --- Я бы взял, пропустил все запросы через explain, посмотрел, какие проблемы выявятся. Плюс веб-сокеты, чтоб не надо было без надобности каждые 5 секунд со всех компов опрашивать.
индексы да проставлены Звучит разумно, лучше написать сокет сервер который будет сам опрашивать сайт и рассылать патчи клиентам? или на прямую из базы брать данные?
Для ларки есть свой сокет сервер на ноде, от сообщества, для проектов средней сложности его обычно более чем. https://github.com/tlaverdure/laravel-echo-server При появлении новых данных он может просто или разослать уведомление, или разослать сами данные клиентам, смотря от объёмов и условий типа авторизации/секретности. Хотя, там есть и приватные каналы, которые защищены. Плюс этого сервера - ларка уже умеет с ним работать. --- Добавлено --- Ну и плюс, через explain убедитесь, что ваши индексы действительно работают. И что-то мне кажется, что кеш на 5 секунд делает только хуже, а не лучше. Через что кешите? --- Добавлено --- Лог медленных запросов пробовали?
через стандартный драйвер = files нагрузка на этот маршрут идет только 3 часа в сутки, и чтобы не все запросы отправлять в бд, я решил сделать кеширование чтобы первый запрос записал в бд а остальные брали из файла через 5 сек данные обновятся и получать новую выдачу.
типичная ошибка, с которой начинал я: собирать сущность игрока на основании сущностей того, что ему принадлежит, да ещё и выполняя кучу джоинов (хотя это и не смертельно, правильный джоин при USING, а не при тупом сравнении, не упадёт даже при ляме запросов), завершилось всё тем, что сущность игрока перекочевала в сущность юзера, которая определяется на момент проверки авторизации, данные уже есть, плюс всё, что касается сущности юзера-игрока хранится в одной табле (какая разница 5 там или 50 столбцов, всё выбирается за один раз) и если нам нужно обновить юзера-игрока, то мы не лазим по всему скрипту и всей БД - мы просто делаем $user->property = что-то, и перед вбросом в рендер делаем $user->save, получая самые последние данные обновляя таблу user один раз и только её то есть в чём суть: я просто данные из базовых таблиц переношу в таблы user-бызовая таблица, иначе если хранить просто user-айди_базовой таблицы, то на момент вывода данных юзера-игрока, мы задолбаемся собирать его по всем базовым таблам лазя по их айдишникам, принадлежащим юзеру-игроку короче тут долго пояснять, выглядит это так: если юзеру присвоен ранг и есть базовая таблица раногов, то не нужно писать юзеру афдишник ранга, нужно тупо прописать ему этот ранг в его таблу, чтобы при выводе ранга юзера не делать запрос по айдишнику ранга к базовой таблице рангов ))) --- Добавлено --- а какой смысл кеша в 2021-ом году, PHP видимо быстрее к кешу обратится, чем к БД, которая на SSD стоит? --- Добавлено --- 70 человек и сервак падает, 10 лет назад при онлайне в 100 падал сервак если там толпой монстра били, так там на процедурке скрипт на пару метров работал, а тут ясен пень фреймворк стоит на 50 метров думает полчаса, как ему один запрос защитить от падения, а тут целых 70)))
смысл наверное не в скорости доступа - а в снижении нагрузки на БД. Зачем лишний раз ее дергать, когда можно из кеша готовое достать
70 человек и сервак падает, 10 лет назад при онлайне в 100 падал сервак если там толпой монстра били, так там на процедурке скрипт на пару а логика в чём? засунуть в кеш базовые таблы? и что будет быстрее: запрос к БД на SSD или достать из файла - это мы разницу под микроскопом рассмотрим? а вот собирать сущность кучей запросов к базовым таблицам - это вот полна дичь, направленная на повышение зарплаты от того что у нас не в одной табле всё, а в паутине да ещё и для понта связей понаделать чтобы нельзя было дичь поудалать