Селект с пагинацией без селекта всех записей
Есть проект на laravel, в одном из методов по получению списка заявок я получаю общее кол-во заявок для пагинации и потом 20 из этого числа по смещению. На проде кол-во заявок уже около 150к, время выполнения не самое радужное, около 3 секунд У меня подозрения, что в момент фильтрации заявок Eloquent берет все записи, оттуда и долгое ожидания Если так, то есть ли способ не брать все заявки? Код таков:
$filter = app()->make(OrderFilter::class, ['params' => ArrayHelper::filter($data)]);
$query = Order::filter($filter)
->whereHas('client')
->where('something', '=', 1)
->orderBy($sort, $order);
$count = $query->count();
$query = $query->limit($limit)->offset(($page - 1) * $limit);
// something
return [/*data from $query*/];
Я смотрел решения с помощью чанков, но это не подходит, ибо данные после всех манипуляций летят на фронт, чанки тут бесполезны будут
Ответы (1 шт):
Общие рекомендации
Полагаю, что для параметра "something" у модели Order необходимо добавить индекс в таблицу orders, и затем использовать этот параметр первым в запросе.
Долгим может быть именно запрос по по подсчету кол-ва заявок в таблице, поскольку выполняется обход всех требуемых строк.
Для ускорения подобного мероприятия, можно попробовать переписать пагинацию по типу Cursor-пагинация - https://laravel.su/docs/8.x/pagination#cursor-paginaciia Для Cursor-пагинации используется несколько иной и более быстрый принцип выбора данных и формирования ссылок на страницы. Это подойдет в том случае, если ссылки на каждую страницу с заявками - не критичный функционал. То есть Cursor-пагинация даст ссылки только на следующую и предыдущую страницы.
Рекомендую использовать, как минимум, Debug-bar для Laravel, чтобы выяснить какой именно запрос выполняется долго, и затем оптимизировать.