MySQL - 选择关系数据避免左连接的最快方法

时间:2012-04-05 11:14:54

标签: mysql performance select join

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

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

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

2 个答案:

答案 0 :(得分:4)

这里有两个问题:

  1. 如何在不到2秒的时间内获得结果
  2. 如何避免左连接。
  3. 要正确回答#1,必须提供更多信息。技术信息,例如此特定查询的解释计划是一个良好的开端。如果我们拥有您访问的所有表的SHOW CREATE TABLE以及它们包含的行数,那就更好了。

    但我也很欣赏更多功能性信息:您要回答的问题究竟是什么?现在,看起来你正在看两组不同的媒体:

    1. 在projectsExt中没有匹配的行,在这种情况下medias.ownerUser必须等于'1'(那个'1'应该是一个字符串btw?)
    2. 或者projectsExt中只有一个mathing行,其中projectsExt.user必须等于'1'(那个'1'应该是一个字符串btw?)
    3. 由于缺乏足够的信息来回答#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
      

答案 1 :(得分:0)

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

子选择的性能低于连接,因为引擎可以将连接优化到更高的程度。实际上,在适用的情况下,子选择通常会在可能的情况下被引擎重写为连接。

作为一个经验法则,分割查询没有任何好处,你获得的只是开销和混淆优化器。这个规则一如既往地存在例外情况,但是在您完成传统工作并且知道自己热衷于这种方法之后,它们就会发挥作用。