zvermafia
@zvermafia
WebDev

Можно ли оптимизировать этот запрос к БД?

Есть каталог сайтов (сайты проверяются перед добавлением в каталог, то есть со статусом `отклонен = 0` и `принят = 1`), у сайтов есть теги. Так вот я хочу вывести все теги с отношениями с сайтами со статусом `принят` (случайным образом по 50 шт.).

Для тегирования использую пакет `cartalyst/tags: v2.1`, и для удобства создал модель `Tag` и настроил отношения (так как сам пакет не предоставляет модель для прямой работы с тегами)...

Сам запрос выглядит так:
$tags = Tag::whereHas('catalogue', function ($query) {
        $query->where('status', 1);
    })
    ->orderBy(DB::raw('RAND()'))
    ->take(50)
    ->get();


Но теперь `response time` увеличился до ~9 секунд, раньше было ~1.5 секунд (это почему-то моя ВМ так тормозит, в продакшене ~0.4 ms).

Как оптимизировать выше указанный код?
Я бы хотел закешировать максимум на 5 минут, но 9 секунд на каждые 5 минут это очень много...
  • Вопрос задан
  • 376 просмотров
Решения вопроса 3
Denormalization
@Denormalization
Тормазит из-за order by rand().
Сколько записей? Может проще вытащить все и закешировать их? И потом средствами PHP просто выбирать рандомные.
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
->orderBy(DB::raw('RAND()'))


вот в этом проблема.

Если бы у вас гарантировано небыло дырок в ID-никах, можно было бы взять минимальный айдишник, максимальный айдишник, сгенерить 50 айдишек рандомных и сделать простой where in. Все остальные варианты - вариации этого.

https://www.warpconduit.net/2011/03/23/selecting-a...
Ответ написан
Комментировать
un1t
@un1t
"order by rand()" выполяется медленно

можно у каждого тега при создании сохранять случайное число от 0 до 1, потом при выборке генерировать случайное число от 0 до 1 и выбирать "where tag.randint > случайное_число order by tag.randint". Не забудь индекс построить по данному полю.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы