Php Laravel/MYSQL(雄辩)-查询大表

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\

我正在制作一个在线目录,该目录包含业务,这是当前表结构的设置方式:

1) “业务”

  • ID(主键)
  • 名字
  • 电话号码
  • 电子邮件
2) 标签

  • id(主键)
  • 标签
3) 商务标签

  • id(主键)
  • 企业识别码(FK)
  • 标签标识(FK)
业务表中有超过9k行,在(“业务_标记”)表中有超过84269行和29k行(因为一个业务可以有多个标记)

在业务模型内部,有以下内容:

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行对于透视表来说并不多。