2016-04-03 107 views
2

我正在使用此查詢來篩選出具有城市和類別的商店。當我在stores表中有大約1000條記錄時,它工作正常。現在,當我有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%,但是這個_應該生成合理的SQL。 –

+0

@JoachimIsaksson是的,這兩個表都有索引。通過運行這個命令'SHOW INDEX FROM stores;'來確認。 –

+1

看看這個問題它可能會幫助你,並特別評論凱伊斯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

好的解決方案:)。讓我知道你是否正在古爾岡尋找一份工作。 –

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 

在數據庫工具告訴你究竟是什麼發生的事情,是否你真的有指標所有需要的東西。

看你查詢你應該有索引stores爲列:

  • city_id
  • 禁用
  • 評級

categories你應該有索引列:

  • CATEGORY_ID
  • STORE_ID

或這些列的一些組合。