子查询中最有效的过滤器位置(GROUP BY)在JOIN中

时间:2013-10-02 05:06:09

标签: mysql performance optimization join filter

SELECT * FROM foo f
INNER JOIN (
    SELECT bar_id, MAX(revision_id) FROM bar b
    GROUP BY bar_id
) t ON t.bar_id = f.bar_id

好的,所以听到这个问题:让我们说这些表中有数百万条记录,我希望查询尽可能高效。

MySQL是否会拉出条形表的所有记录,然后在连接级别的ON语句中而不是在子查询中过滤它们?或者有没有办法在JOIN过滤器之前用SQL本身过滤子查询中的项目?

似乎查询过滤掉它们的所有记录都效率低下,我还没有想过要解决这个问题的方法。

我试过这个,但子查询无法看到foo表:

SELECT * FROM foo f
INNER JOIN (
    SELECT bar_id, MAX(revision_id) FROM bar b
    WHERE b.bar_id = f.bar_id
    GROUP BY bar_id
) t ON t.bar_id = f.bar_id

有没有办法将id传递给子查询,我只想以最佳方式做事,我确信有办法做到这一点。

感谢所有回复。

1 个答案:

答案 0 :(得分:0)

  

MySQL是否会拉出条形表的所有记录,然后在连接级别的ON语句中而不是在子查询中过滤它们?

最有可能的是,它会在进行连接之前完整地执行子查询。如果您想确切知道,请查看执行计划,EXPLAIN显示它。

有一种特殊情况,这种方法甚至可能是有益的:如果bar很大但bar_id只需要很少的值,而foo的很多行都会引用这几个{ {1}}值,然后在将每个id连接到bar_id行之前选择每个id的最大修订版可能会很好。

  

或者有没有办法在foo过滤器之前只使用SQL过滤子查询中的项目?

您可以完全避免使用子查询:

JOIN

我假设SELECT f.*, MAX(b.revison_id) FROM foo f INNER JOIN bar b ON b.bar_id = f.bar_id GROUP BY f.foo_id 中的每一行都可以由foo唯一标识;您可能必须在那里使用多个列,或引入新密钥。因此,结果将在foo_id中的每一行中包含一行,但前提是foo中至少还有一个匹配的行。 bar中的所有行都将在bar调用中汇总,因此您可以从这些行中获得最大MAX

  

我试过这个,但是子查询无法看到foo表:[...]

这不好用。 工作的关闭事物将是一些依赖查询,其必须重复执行,每个foo行一次。哪个是性能杀手。如果有疑问,请尝试使用您的实际数据并简单地比较执行时间,以便进行足够多的执行。

结论:尽量避免使用subquerys,并尽量避免使用依赖子查询。