small/medium 个表上的左连接非常慢

Very slow Left Join on small/medium tables

我遇到了一个问题,即某个特定的左连接会大大降低一个重要查询的速度。使用 PHPMyAdmin 测试查询,它指出查询用了 3.9 秒 return 546 行,但我不得不等待 67 秒才能看到让我感到奇怪的结果。

涉及两个table: nsi(1,553 行)和文件(233,561 行)。此查询中提到的所有列都单独索引,并且在文件 table 中的 filejobid、类别和 isactive 上有一个复合索引。所有被比较的东西也是一个整数。

这个简化版本的查询的目标是显示一次来自 nsi table 的行,并能够确定是否有人上传了类别 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 秒加载时间对于我的应用程序来说简直是无法接受table,我不知道如何进一步优化它。我已经建立了索引和复合索引。我是否应该寻找一个新的更迂回的解决方案?

感谢您的帮助!

这是你的查询,我觉得它有点可疑,因为你有聚合但没有 f.id 上的聚合函数。它会return一个任意匹配的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()