Php ';简单';mysql查询需要30秒才能加载

Php ';简单';mysql查询需要30秒才能加载,php,mysql,laravel,laravel-5,Php,Mysql,Laravel,Laravel 5,我正在使用Laravel雄辩的模型创建一个非常基本的MySQL查询。我有三个数据库表:posts、tags和post\u tag(透视表)。我想得到和分页最常用的标签。查询正在运行,但加载大约需要30秒。tags表有约9k条记录,post\u tag表有约26k条记录。但在不久的将来,他们的post_标签表中的记录将超过100万条 代码如下: $tags = Tag::leftJoin('post_tag', 'tags.id', '=', 'post_tag.tag_id') ->

我正在使用Laravel雄辩的模型创建一个非常基本的MySQL查询。我有三个数据库表:
posts
tags
post\u tag
(透视表)。我想得到和分页最常用的标签。查询正在运行,但加载大约需要30秒。
tags
表有约9k条记录,
post\u tag
表有约26k条记录。但在不久的将来,他们的
post_标签
表中的记录将超过100万条

代码如下:

$tags = Tag::leftJoin('post_tag', 'tags.id', '=', 'post_tag.tag_id')
    ->select(\DB::raw('post_tag.tag_id, tags.content, COUNT(`tag_id`) AS `occurrence`'))
    ->groupBy('tag_id', 'content')
    ->orderBy('occurrence', 'desc')
    ->take(15)
    ->paginate(request('per_page'));
如果没有分页,则加载查询大约需要20秒。我不经常使用
groupby
join
查询,但我猜
groupby
需要很多时间


我在Stackoverflow和Google上冲浪,但没有任何运气。有什么建议吗?
索引
会有很大区别吗?

您没有发布样本数据,因此我无法进行任何测试

这只是一个想法,所以如果它不起作用,我会删除答案

我在想,您可以尝试(并检查性能)改变您的查询(据我所知,阅读您的代码)

(更新:感谢罗兰·斯塔克增加了限制条款)

对于这一点:

SELECT A.TAG_ID, B.CONTENT, OCCURRENCE
FROM (SELECT TAG_ID, COUNT(*) AS OCCURENCE 
      FROM POST_TAG 
      GROUP BY TAG_ID 
      ORDER BY OCCURRENCE DESC LIMIT 15) A
INNER JOIN TAGS B ON A.TAG_ID= B.ID
ORDER BY OCCURENCE DESC;

请让我知道

IMHO,最好在创建相应的表、索引和外键后定义模型关系,并利用Laravel Elount来完成这项工作。 我几乎从来没有在我的Laravel项目中使用query builder来创建查询,相反,正如我所说,我花时间和精力来设计数据库表和相应的模型以及它们之间的关系,这向我证明,最终得到的代码更干净,性能更好。同样,这只是我个人的观点。 话虽如此,我展示了一段代码,它产生了您想要的结果:

假设有表:posts、tag和post_tag。后者将post_id和tag_id字段声明为索引,并将外键指向它们的相关表

定义模型关系:

标签型号:

public function posts()
{
    return $this->belongsToMany(Post::class);
}
关于Post模型:

public function tags()
{
   return $this->belongsToMany(Tag::class);
}
在控制器上:

$tags = \App\Tag::withCount('posts')->orderBy('posts_count', 'DESC')->paginate(10);
要意识到一个标签所拥有的帖子数量实际上就是它的出现


Laravel文档的相关主题:

为什么要同时按标记id和内容进行分组?否则mysql抛出错误:
1055 Expression\35; SELECT list的2不在GROUP by子句中,并且包含未聚合的列
Yes,列上的索引可能会减少运行时间,也会减少您分组的列数。将索引添加到
tag\u id
content
可以显著缩短执行时间。现在需要450毫秒。@RolandStarke谢谢。。。更新后的answerI'v以前从未使用
with count()
方法。非常有用,每天学点东西:-)。干杯
$tags = \App\Tag::withCount('posts')->orderBy('posts_count', 'DESC')->paginate(10);