我正在使用此查询过滤出包含城市和类别的商店。当我在stores
表中有大约1000条记录时,它工作正常。现在,当我有5000条记录时,生成结果大约需要3-10秒。
在我的案例中,商店属于多个类别。
如何使用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);
答案 0 :(得分:5)
我使用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);
答案 1 :(得分: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
编制索引:
和categories
你应该有列的索引:
或这些列的某些组合。