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()
。
我遇到了一个问题,即某个特定的左连接会大大降低一个重要查询的速度。使用 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()
。