我正在制作一个在线目录,这个目录包含商家,这就是当前表结构的设置方式:
1)“商业”
2)标签
3)Business_tags
业务表内部有超过9k行,超过84,269行,(“Business_tags”)表中有超过29,000行(因为企业可以有多个标记)。
在商业模式中,有如下内容:
public function tags()
{
return $this->belongsToMany('App\Tags');
}
问题是当我尝试进行搜索时,例如,假设有人想要搜索“中文”,那么它需要的时间比返回值的时间要长。例如,我正在使用:
$business = Business::where(function ($business) use ($request) {
$business->whereHas('tags', function ($tag) use ($request) {
});
})->paginate(20);
平均搜索:35秒显示结果。
这是原始的sql:
select * from `businesses` where (exists (select * from `tags` inner join `business_tags` on `tags`.`id` = `business_tags`.`tags_id` where `business_tags`.`business_id` = `businesses`.`id` and `name` in ('chinese')))
平均值:52.4秒在Sequel pro中运行(使用原始SQL语句)
任何想法如何提高此查询的性能以便更快?我希望拥有此功能,但用户不会等待这么长时间来回复!
编辑:
1 PRIMARY businesses NULL ALL NULL NULL NULL NULL 8373 100.00 Using where
2 DEPENDENT SUBQUERY business_tags NULL ALL NULL NULL NULL NULL 30312 10.00 Using where
2 DEPENDENT SUBQUERY tags NULL eq_ref PRIMARY PRIMARY 4 halalhands.business_tags.tags_id 1 10.00 Using where
答案 0 :(得分:1)
很多人也会告诉你。
EXPLAIN
?JOIN
是否可以在这里工作,是否更快?(只是一个想法)答案 1 :(得分:1)
你过度复杂了,没有正确使用雄辩的关系。你应该使用JOIN代替:
$businesses = Business::join('business_tags', 'business_tags.business_id', '=', 'business.id')
->join('tags', function($join) {
$join->on('business_tags.tag_id', '=', 'tags.id')
->where('tags.name', '=', 'chinese');
})->get();
或者在原始SQL中:
SELECT *
FROM `business`
INNER JOIN `business_tags` ON `business_tags`.`business_id` = `business`.`id`
INNER JOIN `tags` ON `business_tags`.`tag_id` = `tags`.`id` AND `tags`.`name` = 'chinese'
(请注意,您可以将tags.name = 'chinese'
部分放在WHERE子句中并产生相同的效果)
您当前的查询执行一个存在子查询,以获取数据透视表中符合条件的所有记录,然后将其传递回主查询。这是一个额外的步骤,这是不自然的。
雄辩的关系不适用于像这样的复杂查询,而是提供有关记录的其他相关信息,而无需手动编写其他查询。
例如,如果要查看业务,可以从其他表中查询with()
电话号码和地址。您可能希望列出其标记,或sync()
它们。但eloquent不构建和过滤查询,这就是查询构建器的用途。
如果您需要更多解释,请告诉我。