MySQL - 如何优化表b中的附加字段到表a的查询

时间:2013-06-28 06:33:12

标签: mysql join

我知道这必须是一个相当普遍的问题,我确信答案很容易获得,但我不确定如何对我的搜索进行说明,因此我大部分时间都不得不自行解决这个问题。< / 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秒钟可以减少一半。我只是在内心深处感受到它。在我的内心深处。

我希望这很简洁,如果我需要澄清或解释更好的东西,请告诉我!提前谢谢。

2 个答案:

答案 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 MariaDBMySQL 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检查查询执行计划