2

我目前有一个查询,它从两个表中选择指标数据,同时让项目从另外两个表中查询(一个是拥有的项目,另一个是用户有权访问的项目)。

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秒。这显然是多左连接场景。但是,我有一些想法可以提高速度,并且想知道这些想法原则上是什么。我是否:-

  • 尝试在查询中选择列表,然后获取数据,而不是进行连接。不知道这将如何工作。
  • 在单独的查询中进行选择以获取 projectID,然后在每个 projectID 上运行查询。这可能会导致成百上千的请求,但可能更适合处理?
  • 其他想法?
4

2 回答 2

4

这里有两个问题:

  1. 我怎样才能在不到 2 秒的时间内得到结果
  2. 我怎样才能避免左连接。

要正确回答#1,必须有更多信息。技术信息,例如这个特定查询的解释计划是一个好的开始。如果我们有您访问的所有表的 SHOW CREATE TABLE 以及它们包含的行数,那就更好了。

但我也很欣赏更多功能信息:您要回答的问题到底是什么?现在,您似乎正在查看两组不同的媒体:

  1. 要么projectExt中没有匹配的行,在这种情况下medias.ownerUser必须等于'1'('1'应该是一个字符串btw吗?)
  2. 或者 projectsExt 中只有一个数学行,projectExt.user 必须等于 '1' ('1' 应该是一个字符串 btw 吗?)

由于缺乏足够的信息来回答#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
于 2012-04-05T14:31:42.287 回答
0

相反,您是否尝试过将所有内容重构为左连接?看到你总是在同一个领域分组,这应该不是问题。试试这个并发布一个EXPLAIN看看瓶颈是什么。

子选择的性能不如连接,因为引擎可以将连接优化到更高的程度。事实上,子选择通常会在可能的情况下由引擎重写为连接。

根据经验,拆分查询没有任何好处,您获得的只是开销和混淆优化器。与往常一样,这条规则也有例外,但在您完成了传统上可以做的事情并且知道您热衷于这种方法之后,它们就会发挥作用。

于 2012-04-05T14:00:43.973 回答