Мне нужно выбрать все команды, в которых в данный момент зарегистрирован пользователь, и это мой Eloquent код:
$teams = Team::orderBy('created_at', 'desc')->get()->filter(function($team) use ($user)
{
return $team->inTeam($user);
});
Списки команд — это массивы идентификаторов пользователей, которые хранятся в виде строки в базе данных.
Это функция inTeam:
public function inTeam($user)
{
$id = $user->id;
$players = $this->getPlayers();
foreach ($players as $p)
{
if (is_null($p)) continue;
if ($p == $id) return true;
}
return false;
}
При загрузке страницы с этим кодом загрузка моего сервера увеличивается примерно до 60% на apache2 и около 30% на mysqld, и я не могу понять, почему. С помощью filter()
Модель Team — это самый чистый способ, который я нашел, делать то, что мне нужно, и это просто вызывает проблемы, даже останавливая сайт, когда достаточное количество пользователей загружает страницу.
Можно ли каким-то образом оптимизировать фильтрацию или мне нужно изменить структуру базы данных, в которой хранится информация реестра?
Изменить: я обновил свой код для использования FIND_IN_SET и удалось сократить время процессора до 5 с 8 с. Все еще не идеал, как бы то ни было.
$teams = Team::orderBy('id', 'desc')->whereRaw("FIND_IN_SET(" . $user->id . ", players_list)")->get();
Я понятия не имею, как бы я нормализовал свою базу данных для этого, так как players_list
столбец имеет другую длину в соответствии с Event
Team
связано, следовательно, разделенные запятой строки.
Фильтрация означает, что вы извлекаете все данные из MySQL и затем выполняете поиск в большом массиве, содержащем результат.
Для больших наборов данных я рекомендую использовать условие SQL вместо фильтрации на стороне php.
Пожалуйста, опубликуйте больше о вашей базе данных, если вы хотите рабочий фрагмент. В противном случае, проверьте документацию, где / где, и т. Д .: http://laravel.com/docs/5.0/eloquent#basic-usage
Других решений пока нет …