我知道这必须是一个相当普遍的问题,我确信答案很容易获得,但我不确定如何对我的搜索进行说明,因此我大部分时间都不得不自行解决这个问题。< / p>
表A
id | content_id | score
1 | 2 | 16
2 | 2 | 4
3 | 3 | 8
4 | 3 | 12
表B
id | content
1 | "Content Goes Here"
2 | "Content Goes Here"
3 | "Content Goes Here"
目标:将表A中的所有分数,由唯一的content_id分组,并显示与ID相关联的内容,按总分排序。
当前工作查询:
SELECT a.content_id, b.content, SUM(a.score) AS sum
FROM table_a a
LEFT JOIN table_b b ON a.content_id = b.id
GROUP BY a.content_id
ORDER BY sum ASC;
问题:据我所知,通过我构建查询的方式,通过循环遍历table_a上的每条记录,从table_b中获取内容,检查table_b中的记录相同的ID,并抓取内容字段。这里的问题是table_a中有近500k +记录,而table_b中有112条记录。这意味着正在执行可能的500,000 x 112个交叉表查找/匹配,仅将112个唯一内容字段附加到结尾结果集中的总共112个结果中。
帮助!:如何更有效地将table_b中的112个内容字段附加到查询生成的112个结果中?我猜测它与查询执行顺序有关,就像某种程度上只查找并将内容字段附加到匹配的结果行之后产生的总和它被缩小到只有112条记录?已经研究过MySQL API并对各种子查询进行了基准测试,有几个连接,甚至尝试过使用UNION。对你们来说这可能是非常明显的事情,但是我的大脑无法绕过它。
仅供参考:如前所述,查询确实有效。结果在大约8到10秒内生成,当然,由于查询缓存,后面的每个后续查询都是立即的。但对我来说,这是多么简单,我知道8秒钟可以减少一半。我只是在内心深处感受到它。在我的内心深处。
我希望这很简洁,如果我需要澄清或解释更好的东西,请告诉我!提前谢谢。
答案 0 :(得分:2)
MySQL查询优化器只允许“nested loop joins”**这些是如何评估INNER连接的内部运算符。其他RDBMS允许其他类型的JOIN更有效。
但是,在您的情况下,您可以试试这个。希望优化器在 JOIN之前进行聚合
SELECT
a.content_id, b.content a.sum
FROM
(
SELECT content_id, SUM(score) AS sum
FROM table_a
GROUP BY content_id
) a
JOIN table_b b ON a.content_id = b.id
ORDER BY
sum ASC;
此外,如果您不希望订购结果,则可以使用ORDER BY NULL
,这通常会从filesort
中删除EXPLAIN
。当然,我假设2 content_id
列上有索引(一个主键,一个外键索引)
最后,我还假设INNER JOIN足够了:a.contentid
中存在tableb
。如果没有,您在a.contentid
**它越来越好,但you need MariaDB或MySQL 5.6
答案 1 :(得分:1)
这应该快一点:
SELECT
tmp.content_id,
b.content,
tmp.asum
FROM (
SELECT
a.content_id,
SUM(a.score) AS asum
FROM
table_a a
GROUP BY
a.content_id
ORDER BY
NULL
) as tmp
LEFT JOIN table_b b
ON tmp.content_id = b.id
ORDER BY
tmp.asum ASC
当您想要对两个查询进行基准测试时,可以使用EXPLAIN
检查查询执行计划