所以我的查询完全符合预期,但需要大量优化。我正在使用软件来跟踪我网站上的加载时间,并且我网站上97.8%的加载时间是这一功能的结果。所以在进入查询之前先解释一下我的数据库。
首先,我有一张电影桌,一张比赛表和一张投票表。电影可以参加许多比赛,比赛有很多电影,因为这是一个多对多的关系,我们有一个数据透视表来显示他们的关系(电影竞赛)当加载比赛页面时,这些电影需要按照他们的投票顺序(大多数)投票在顶部。最少在底部。)
现在在下面的查询中,您可以看到我正在做的事情,从电影竞赛表中获取与当前比赛ID $ competition-> id匹配的电影,然后我按照该电影的总票数进行排序。就像我说的那样有效,但效率很高,但我想不出另一种方法。
$films = DB::select( DB::raw("SELECT f.*, COUNT(v.value) AS totalVotes
FROM filmCompetition AS fc
JOIN films AS f ON f.id = fc.filmId AND fc.competitionId = '$competition->id'
LEFT JOIN votes AS v ON f.id = v.filmId AND v.competitionId = '$competition->id'
GROUP BY f.id
ORDER BY totalVotes DESC
") );
答案 0 :(得分:1)
对于此查询,您需要filmCompetition(competitionId, filmId)
,films(id)
和投票(filmId,competitionId)的索引。
但是,编写这样的查询可能更有效:
SELECT f.*,
(SELECT COUNT(v.value)
FROM votes v
WHERE v.filmId = f.id and v.competitionId = '$competition->id'
) AS totalVotes
FROM films f
WHERE EXISTS (SELECT 1
FROM FilmCompetition fc
WHERE fc.FilmId = f.Filmid AND
fc.competitionId = '$competition->id'
)
ORDER BY TotalVotes DESC
这样可以保存外部聚合,这应该是性能上的提升。对于此版本,索引为FilmCompetition(FilmId, CompetitionId)
和Votes(FilmId, CompetitionId)
。
答案 1 :(得分:0)
我实际上最终使用的解决方案有点不同,但自从戈登回答了这个问题后,我将他标记为正确答案。
我的解决方案 为了实际修复这个问题,我做了一个稍微不同的方法,而不是尝试在SQL中完成所有这些操作,我分别完成了三个查询,然后在PHP中将它们连接在一起。虽然在我的情况下,这可能会慢一点,我的原始方式需要大约15秒,这样做Gordons的方式大约需要7秒,而这样做我的新方式需要大约600毫秒。