我目前有一个查询,它从两个表中选择指标数据,同时从另外两个表中获取要查询的项目(一个是拥有的项目,另一个是用户有权访问的项目)。
SELECT v.`projectID`,
(SELECT COUNT(m.`session`)
FROM `metricData` m
WHERE m.`projectID` = v.`projectID`) AS `sessions`,
(SELECT COUNT(pb.`interact`)
FROM `interactionData` pb WHERE pb.`projectID` = v.`projectID` GROUP BY pb.`projectID`) AS `interactions`
FROM `medias` v
LEFT JOIN `projectsExt` pa ON v.`projectsExtID` = pa.`projectsExtID`
WHERE (pa.`user` = '1' OR v.`ownerUser` = '1')
GROUP BY v.`projectID`
时间太长,1-2秒。这显然是多左连接场景。但是,我有一些提高速度的想法,并且想知道这些想法的原则是什么。我做吗:-
- 尝试选择查询中的列表,然后获取数据,而不是进行联接。不确定这将如何运作。
- 在单独的查询中进行选择以获取项目 ID,然后对每个项目 ID 运行查询。这可能会导致数百个潜在的数千个请求,但可能更适合处理?
- 还有其他想法吗?
最佳答案
这里有两个问题:
- 如何在 2 秒内获得结果
- 如何避免左连接。
要正确回答第一个问题,必须有更多信息。技术信息(例如此特定查询的解释计划)是一个好的开始。如果我们能够显示您访问的所有表的 SHOW CREATE TABLE 以及它们包含的行数,那就更好了。
但我也希望获得更多功能性信息:您想要回答的问题到底是什么?现在,您似乎正在查看两组不同的媒体:
- projectsExt 中没有匹配的行,在这种情况下 medias.ownerUser 必须等于“1”(顺便说一句,“1”应该是字符串吗?)
- 或者在projectsExt 中有一个数学行,其projectExt.user 必须等于“1”(顺便说一句,“1”应该是一个字符串吗?)
由于缺乏足够的信息来回答#1,我可以回答#2 -“如何避免左连接”。答案是:编写两个集合的 UNION,一组匹配,一组不匹配。
SELECT v.`projectID`
, (
SELECT COUNT(m.`session`)
FROM `metricData` m
WHERE m.`projectID` = v.`projectID`
) AS `sessions`
, (
SELECT COUNT(pb.`interact`)
FROM `interactionData` pb
WHERE pb.`projectID` = v.`projectID`
GROUP BY pb.`projectID`
) AS `interactions`
FROM (
SELECT v.projectID
FROM medias
WHERE ownerUser = '1'
GROUP BY projectID
UNION ALL
SELECT v.projectID
FROM medias v
INNER JOIN projectsExt pa
ON v.projectsExtID = pa.projectsExtID
WHERE v.ownerUser != '1'
AND pa.user = '1'
GROUP BY v.`projectID
) v
关于MySQL - 选择关系数据避免左连接的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10027522/