Php Laravel/MYSQL(雄辩)-查询大表
我正在制作一个在线目录,该目录包含业务,这是当前表结构的设置方式: 1) “业务”Php Laravel/MYSQL(雄辩)-查询大表,php,mysql,laravel,laravel-5,eloquent,Php,Mysql,Laravel,Laravel 5,Eloquent,我正在制作一个在线目录,该目录包含业务,这是当前表结构的设置方式: 1) “业务” ID(主键) 名字 电话号码 电子邮件 2) 标签 id(主键) 标签 3) 商务标签 id(主键) 企业识别码(FK) 标签标识(FK) 业务表中有超过9k行,在(“业务_标记”)表中有超过84269行和29k行(因为一个业务可以有多个标记) 在业务模型内部,有以下内容: public function tags() { return $this->belongsToMany('App\
- ID(主键)
- 名字
- 电话号码
- 电子邮件
- id(主键)
- 标签
- id(主键)
- 企业识别码(FK)
- 标签标识(FK)
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')))
在Sequel pro内部运行平均需要52.4s(使用原始SQL语句)
有没有办法提高这个查询的性能,让它更快?我想拥有这个功能,但用户不会等这么久才得到响应
编辑:
正如很多其他人也会告诉你的那样
EXPLAIN
JOIN
是否可以在这里工作,是否更快?(只是一个想法)正如很多其他人也会告诉你的那样
EXPLAIN
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子句中,并产生相同的效果)
当前查询执行exists子查询,以从数据透视表中获取与条件匹配的所有记录,然后将其传递回主查询。这是一个额外的步骤,这是不自然的
雄辩的关系不适用于像这样的复杂查询,而是用于提供有关记录的其他相关信息,而无需手动编写另一个查询
例如,如果要查看业务,可以使用()查询电话号码和其他表中的地址。您可能想列出它们的标记,或者sync()
它们。但Elountit不构建和过滤查询,这就是查询生成器的用途
如果你需要更多的解释,请告诉我。你把这件事复杂化了,而且没有正确使用有说服力的人际关系。您应该改为使用联接:
$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子句中,并产生相同的效果)
当前查询执行exists子查询,以从数据透视表中获取与条件匹配的所有记录,然后将其传递回主查询。这是一个额外的步骤,这是不自然的
雄辩的关系不适用于像这样的复杂查询,而是用于提供有关记录的其他相关信息,而无需手动编写另一个查询
例如,如果要查看业务,可以使用()查询电话号码和其他表中的地址。您可能想列出它们的标记,或者sync()
它们。但Elountit不构建和过滤查询,这就是查询生成器的用途
如果您需要更多解释,请告诉我。您可以使用
chunk
这将加快您的查询速度您定义了哪些索引?@PaulSpiegel我已经设置了索引。我已经为每个表设置了外键,您可以使用chunk
这将加快您的查询速度您定义了哪些索引?@PaulSpiegel我已经设置了索引。我已经为每张桌子设置了外键谢谢,但这不起作用。例如,我有28k个与“tags\u id”1关联的业务标签。。运行您给我的查询,只返回1行。没有别的了。我看不出有什么限制,那会是什么问题呢?(在laravel和sequal pro中运行)还有business.business\u id
指的是什么?在business
表中,只有一列id
,而不是business\u id
?好的,我用正确的表名和一些原始sql更新了我的答案。但除此之外,这应该还可以。你有多少个标签?老实说,28k行对于数据透视表来说并不多。谢谢,但这不起作用。例如,我有28k个与“tags\u id”1关联的业务标签。。运行您给我的查询,只返回1行。没有别的了。我看不出有什么限制,那会是什么问题呢?(在laravel和sequal pro中运行)还有business.business\u id
指的是什么?在business
表中,只有一列id
,而不是business\u id
?好的,我用正确的表名和一些原始sql更新了我的答案。但除此之外,这应该还可以。你有多少个标签?老实说,28k行对于透视表来说并不多。