非常慢左连接小/中表

时间:2015-07-31 15:08:57

标签: mysql left-join query-optimization mysql-slow-query-log

我遇到一个特定的左连接问题,大大减慢了一个重要的查询。使用PHPMyAdmin来测试查询,它声明查询花了3.9秒返回546行,但我不得不等待67秒才能看到结果让我感到奇怪。

涉及两个表格: nsi(1,553行)和文件(233,561行)。此查询中提到的所有列都单独编制索引,并且filebobid,category上存在复合索引,并且在files表中是isactive。所有被比较的东西都是整数。

此查询的淡化版本的目标是一次显示nsi表中的行,并能够确定是否有人上传了类别20中的文件。可以有多个文件但只应该是一行,因此分组。

查询:

SELECT 
    nsi.id AS id,
    f.id AS filein
FROM nsi nsi
LEFT JOIN files f
    ON f.filejobid=nsi.leadid AND f.category=20 AND f.isactive=1
WHERE nsi.isactive=1
GROUP BY nsi.id

此数据的67秒加载时间对于我的应用程序来说简直是不可接受的,我对如何进一步优化它感到茫然。我已编入索引和复合索引。我应该只是寻找一种新的更迂回的解决方案吗?

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

这是您的查询,我觉得有点可疑,因为您在f.id上有聚合但不具有聚合功能。它将返回任意匹配的id:

SELECT nsi.id AS id, f.id AS filein
FROM nsi LEFT JOIN
     files f
     ON f.filejobid = nsi.leadid AND f.category = 20 AND f.isactive = 1
WHERE nsi.isactive = 1
GROUP BY nsi.id;

对于此查询,我认为最佳索引是files(filejobid), category, isactive)nsi(isactive, filejobid, id)

但是,您可以轻松地重写查询以提高效率,因为它不需要group by(假设nsi.id是唯一的):

SELECT nsi.id AS id,
       (SELECT f.id
        FROM files f
        WHERE  f.filejobid = nsi.leadid AND f.category = 20 AND f.isactive = 1
        LIMIT 1
       ) AS filein
FROM nsi 
WHERE nsi.isactive = 1;

相同的索引适用于此。

如果您需要匹配文件列表,而不只是一个,请在任一查询中使用group_concat()