Laravel красноречиво слишком медленно с большим количеством данных - PullRequest
0 голосов
/ 03 мая 2020

Я использую Laravel 7.0 и MySQL 5.7.

Я использую Eloquent для извлечения записей из базы данных, и когда база данных содержит большой объем данных, время отклика становится чрезвычайно медленным.

Ниже приведены несколько примеров:

Movie::where('title', 'LIKE', '%'.$search.'%')->take(10)->get(); для получения первых 10 результатов, соответствующих строке поиска.

Movie::orderBy('rating', 'desc')->take(10)->get() для получения 10 фильмов с самым высоким рейтингом.

Person::has('acted')->orderBy('popularity', 'desc')->take(10)->get() для получения 10 самых популярных актеров .

Когда я использую тестовую базу данных из ~ 1000 записей, время ответа приемлемо, но когда я переключаюсь на живую базу данных из ~ 500 000 записей, это ужасно.

Любые предложения о том, как улучшить производительность приветствуется!

Ответы [ 2 ]

1 голос
/ 03 мая 2020

LIKE '%...' очень неэффективно. Каждая строка должна быть проверена путем сканирования текста.

Гораздо лучше использовать

FULLTEXT INDEX(title)

и

WHERE MATCH(title) AGAINST('+$search')

(Извините, я не знаю как чтобы превратить это в Laravel.)

Mov ie :: orderBy ('rating', 'des c') -> take (10) -> get ()

Это, вероятно, помогает

INDEX(rating)
1 голос
/ 03 мая 2020

Я не думаю, что кому-то нужно будет видеть 500 000 результатов на одной странице, вам нужно разбить его на части и разбить на страницы результаты. Вы также можете использовать chunk или метод cursor . Выберите тот, который наилучшим образом соответствует вашим потребностям.

Если это должен просмотреть пользователь, я бы предложил разбить на страницы результаты. Таким образом, пользователь может go перейти к следующей странице и следующей странице и т.д. c. Или нажмите кнопку «Загрузить еще», чтобы запросить у вашего API загрузку страницы 2, а затем страницы 3 et c.

Если это просто для обработки данных для манипуляции или обновления значений, я бы предложил использовать чанк или курсор .


Для разбивки на страницы:

Movie::where('title', 'LIKE', '%'.$search.'%')->paginate(20);

Это приведет к 20 элементов на странице.

Источник: https://laravel.com/docs/pagination#introduction


К чану:

Movie::where('title', 'LIKE', '%'.$search.'%')->chunk(200, function ($movies) {
    foreach ($movies as $movie) {
        //
    }
});

Это будет вызывать 200 за один раз, затем l oop через них.

Источник: https://laravel.com/docs/eloquent#chunking -результаты


Чтобы использовать метод курсора:

foreach (Movie::where('title', 'LIKE', '%'.$search.'%')->cursor() as $movie) {
    //
}

Это будет перебирать записи вашей базы данных с помощью курсора, который будет выполнять только один запрос.

Источник: https://laravel.com/docs/eloquent#chunking -результаты

Laracasts имеет 10мин видео его объяснение подробно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...