Как ускорить запрос при groupBy?
Как можно ускорить выборку? Записей очень много
$rows->get()->groupBy(function ($item) { return sprintf( '%s by %s', $item->created_at->format('Y-m-d H:i:s'), is_null($item->user) ? 'undefined' : $item->user->getNameAttribute() ); } )->paginate($paginate); |
$rows->get()->groupBy(function ($item) { return sprintf( '%s by %s', $item->created_at->format('Y-m-d H:i:s'), is_null($item->user) ? 'undefined' : $item->user->getNameAttribute() ); } )->paginate($paginate);
Результат моей выбоки
Дополнительно:
1. покажите итоговый запрос
2. покажите используемые индексы
1.Запрос до группировки коллекции
select `revisions`.`id` as `id`, `revisionable_id`, `user_id`, `old_value`, `new_value`, `revision_keys`.`name` as `field_name`, `revision_types`.`name` as `model_name`, `created_at` from `revisions` inner join `revision_keys` on `revisions`.`revision_key_id` = `revision_keys`.`id` inner join `revision_types` on `revisions`.`revision_type_id` = `revision_types`.`id` where `revisionable_id` in (?) and `revision_types`.`name` = ? order by `revisions`.`id` desc |
select `revisions`.`id` as `id`, `revisionable_id`, `user_id`, `old_value`, `new_value`, `revision_keys`.`name` as `field_name`, `revision_types`.`name` as `model_name`, `created_at` from `revisions` inner join `revision_keys` on `revisions`.`revision_key_id` = `revision_keys`.`id` inner join `revision_types` on `revisions`.`revision_type_id` = `revision_types`.`id` where `revisionable_id` in (?) and `revision_types`.`name` = ? order by `revisions`.`id` desc
2. Индексы (revisions_created_at_index,revisions_revision_key_id_foreign,user_id)
выполните explain
кроме того inner join — декартово произведение, лучше сделайте outer (left/right) join
или разбейте запросы на несколько быстрых и выбирайте по индексу записи
Если это прям постоянно нужно, то можно провести денормализацию: добавить модель-таблицу со значением группировки (return sprintf(
'%s by %s',
$item->created_at->format('Y-m-d H:i:s'),
is_null($item->user) ? 'undefined' : $item->user->getNameAttribute()
); и вот это всё), и поле в исходной таблицы с её id, сделать по значению группировки индекс, получать только нужные значения группировки из этой таблицы, а затем после получения страницы уже получать туда нужные данные исходной таблицы, например через https://laravel.com/docs/8.x/eloquent-relationship...
- Кстати я пробовал accessor добавить и запрос стал дольше на пару секунд…
- kaxa3201, я не про изменение текущего запроса, а про изменение структуры БД, дополнительно одна таблица и одна колонка, которые драматически ускорят выборку. Не надо будет читать всю таблицу с огромным количеством строк и большим количеством колонок, надо будет читать только таблицу с двумя колонками, и то не целиком + не целиком, а по индексу читать кусок "большой" таблицы. если чтение происходит чаще (а судя по всему оно происходит чаще), то суммарный выигрыш будет сильно больше, чем увеличение задержки при записи.
Ответы:
Вы путаете запрос к базе и работу с коллекцией.
$rows->get() - вернула вам уже кучу мусора, а дальше вы с ней работаете на стороне php. Делайте группировку на стороне ДБ средствами sql
$rows->groupBy(...)->get()
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос

Для ускорения запроса при использовании оператора groupBy в SQL, можно применить несколько методов оптимизации:
1. Индексы: убедитесь, что у вас есть правильные индексы на столбцы, по которым вы группируете данные. Использование индексов может значительно ускорить выполнение запроса.
2. Оптимизация запроса: избегайте лишних операций и фильтров. Попробуйте оптимизировать запрос, чтобы избежать лишних операций соединения и фильтрации данных.
3. Использование агрегатных функций: если возможно, используйте агрегатные функции вместо оператора groupBy. Например, вместо запроса с groupBy можно написать запрос с использованием функций SUM(), COUNT() и т.д.
4. Предварительная агрегация: если у вас есть возможность, предварительно агрегируйте данные перед выполнением оператора groupBy. Это может существенно сократить объем данных, с которыми нужно работать.
Пример использования индексов для ускорения запроса с оператором groupBy в SQL (например, на языке PHP):
CREATE INDEX idx_column_name ON table_name (column_name);
Эти методы помогут вам ускорить выполнение запросов с оператором groupBy и повысить производительность вашей базы данных.