Я столкнулся с проблемами производительности приложения Laravel, развернутого в производственной среде. Приложение предназначено для регистрации просмотров видео и использует метод firstOrNew
для получения или создания записей устройства для каждого просмотра. Однако независимо от того, является ли трафик интенсивным или умеренным, приложение сталкивается с постоянными таймаутами базы данных, особенно при взаимодействии с таблицей devices
, которая содержит около 20 миллионов записей. Кроме того, бывают случаи, когда выполнение одного запроса к базе данных занимает более 30 секунд. Стоит отметить, что используется база данных MariaDB.
public function store(Request $request){
// define message for when view is already registered
$mssg = 'view already exist';
try{
// Start database transaction
// Retry 3 times if first attempt fails (this is done to avoid db deadlock issues)
DB::transaction(function () use ($request, $mssg) {
// get request data
$ip = $request->ip();
$videoId = $request->input('video_id');
$hostname = $request->has('embed_source') ? $request->input('embed_source') : NULL;
// check if view already counted
if (View::where(['ip' => $ip, 'video_id' => $videoId])->count()) throw new Exception($mssg);
// Register new view
// Firstly, retrieve or create device
$agent = new Agent();
$position = Location::get($ip);
$device = Device::firstOrNew(
[
'type' => $agent->isDesktop() ? 'desktop' : ($agent->isTablet() ? 'tablet' : ($agent->isPhone() ? 'phone' : 'unknown')),
'browser' => strtolower($agent->browser()),
'country' => $position && $position->countryName ? strtolower($position->countryName) : null,
'region' => $position && $position->regionName ? strtolower($position->regionName) : null,
'city' => $position && $position->cityName ? strtolower($position->cityName) : null,
'hostname' => $hostname,
],
[
'long' => $position && $position->longitude ? $position->longitude : null,
'lat' => $position && $position->latitude ? $position->latitude : null,
]
);
$device->save();
// Secondly, save new view with device ID
$view = new View();
$view->video_id = $videoId;
$view->device_id = $device->id;
$view->ip = $ip;
$view->watched_duration = 1;
$view->save();
// Lastly, increment views count in videos table
Video::where('id', $videoId)->increment('total_views');
}, 3);
return response(['viewed' => true], 200);
}catch(\Throwable $e){
if ($e->getMessage() == $mssg) return response(['message' => $mssg], 200);
info($e->getMessage(), [
'title' => 'COULD NOT REGISTER VIEW',
]);
return response(['error' => $e->getMessage()], 500);
}
}
Я не уверен в основной причине этой проблемы и в том, как лучше всего ее решить.
Мне нужны рекомендации о том, как оптимизировать код, чтобы повысить производительность и предотвратить тайм-ауты базы данных при попытке чтения из таблицы devices
. В частности, мне нужны рекомендации по альтернативным подходам к получению или созданию записей об устройствах, оптимизации запросов к базе данных и масштабированию приложения для эффективной обработки текущей рабочей нагрузки.
Мы будем очень признательны за любые идеи, предложения или лучшие практики. Спасибо заранее за вашу помощь!
ваш вопрос неясен, вы столкнулись с проблемой при получении 20 миллионов данных или вы пытаетесь вставить 20 миллионов данных за один раз, помимо этого, насколько я понимаю, ответ на ваш один запрос занимает около 30 секунд, что очень много для любой пользователь, для этого вы можете использовать Jobs/Queue в laravel, чтобы любая часть вставки данных происходила в бэкэнде, и ваш сервер также не загружал слишком много
Вот некоторые (возможные) улучшения:
Не используйте count()
для проверки наличия записи, используйте exists()
Создайте составной уникальный индекс для столбцов type
, browser
, country
, region
, city
, hostname
в базе данных или создайте уникальный столбец hash
и проверьте хэш этих значений.
Если вы добавили отдельные индексы для этих столбцов, удалите их. Это может замедлить операции записи.
Довольно сложно предложить какую-либо оптимизацию запросов к базе данных, если мы не знаем, какие запросы к базе данных выполняются, каков план их выполнения и какова базовая структура данных.