2016-04-03 4 views
2

Я использовал этот запрос, чтобы отфильтровать магазины с городом и категориями. Он работал нормально, когда у меня было около 1000 записей в таблице stores. Теперь, когда у меня 5000 записей, для получения результата требуется около 3-10 секунд.Как оптимизировать этот запрос с помощью whereHas?

Магазин относится ко многим категориям в моем случае.

Как я могу оптимизировать этот запрос, используя Eloquent orm или DB::raw()?

$stores = Store::where('city_id', $city_id) 
     ->where('disabled', '0') 
     ->whereHas('categories', function($q) use ($category_id){ 
      $q->where('category_id', '=', $category_id); 
     }) 
     ->orderBy('rating','DESC')->paginate(10); 
+2

У вас есть какие-то индексы по таблицам? Трудно сказать 100% от запроса в красноречивой форме, но этот _should_ генерирует разумный SQL. –

+0

@JoachimIsaksson Да, обе таблицы имеют индексы. Просто подтвердили, выполнив эту команду 'SHOW INDEX FROM stores;'. –

+1

Взгляните на эту проблему, это может помочь вам и особенно комментарий kaymes https://github.com/laravel/framework/issues/3543 –

ответ

3

Я решил свою проблему, используя whereRaw как DB::raw() или DB::select() не может paginate() сбор.

Проблема: Время

Исполнение: 11.449304103851s

city_id = 6 & $category_id = 1

$stores = Store::where('city_id', $city_id) 
     ->where('disabled', '0') 
     ->whereHas('categories', function($q) use ($category_id){ 
      $q->where('category_id', '=', $category_id); 
     }) 
     ->orderBy('rating','DESC')->paginate(10); 

Решение:

время выполнения: 0.033660888671875s

city_id = 6 & $category_id = 1

$stores = Store:: 
    where('city_id', $city_id) 
    ->where('disabled', '0') 
    ->whereRaw('stores.id in (select store_id from store_categories_pivot where category_id = ?)', [$category_id]) 
    ->orderBy('rating','DESC') 
    ->paginate(10); 
+0

Хорошее решение :). Сообщите мне, если вы ищете работу в Гургаоне в качестве SE. –

1

Вы можете попробовать бег:

$stores = Store::where('city_id', $city_id) 
     ->where('disabled', '0') 
     ->leftJoin('categories','categories.store_id','=', 'stores.id') 
     ->where('category_id', $category_id) 
     ->orderBy('rating','DESC')->paginate(10); 

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

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

EXPLAIN your_query 

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

Глядя на ваш запрос, вы должны, вероятно, индексы для stores столбцов:

  • CITY_ID
  • инвалидов
  • рейтинг

и categories вы должны иметь индексы для столбцов:

  • category_id
  • store_id

или для некоторых комбинаций этих столбцов.

Смежные вопросы