我有一个列表,我从laravel返回产品,这个列表有每列的搜索框,为此,我使用的东西,如:
$q = Product::query();
$q->where('account_id', Auth::user()->account_id);
if ($request->code) {
$q->where('code', 'LIKE' , "%{$request->code}%");
}
if ($request->title) {
$q->where('title', 'LIKE' , "%{$request->title}%");
}
if ($request->price){
$q->whereHas('price', function($query) use ($request){
$query->where('price' ,$request->price);
});
}
$products = $q->with('price', 'images')
->orderBy('id','desc')->paginate($limit);
当我不使用价格部分时,没有问题而且非常快,但是当我使用价格时,则需要很长时间。价格列是小数。
产品 - >价格的关系是:
public function price()
{
// hasOne(RelatedModel, foreignKeyOnRelatedModel = product_id, localKey = id)
return $this->hasOne(Price::class);
}
实际上,我可以使用原始查询和连接,但因为我使用链查询和分页我不能这样做。
有什么建议可以让这个过程更快吗?
根据评论,生成的查询有一个LIKE子句。
SELECT * FROM products
WHERE EXISTS ( SELECT * FROM product_prices
WHERE products.id = product_prices.product_id
AND price LIKE ? )
这不仅会将过滤器中使用的值,而且还会将product_prices表中的所有值转换为字符串,以便计算匹配项。这意味着不使用索引,因此查询变为全表扫描,这比索引查找慢。
我假设使用的实际代码已经复制/粘贴代码和标题的其他子句;因此它也使用LIKE查询。但是,实际问题中没有显示。
解决方案是进行正常的相等比较,这允许使用现有索引。
SELECT * FROM products
WHERE EXISTS ( SELECT * FROM product_prices
WHERE products.id = product_prices.product_id
AND price = ? )
创建另一个迁移和add an index到price
表中的prices
列:
$table->index('price');