什么查询最快?

时间:2010-12-17 13:44:17

标签: mysql optimization join subquery

我有三种方法来构建我的查询:

第一个:

select obj from table1 where condition1 and obj in (
select obj from table2 where condition2 and obj in (
select obj from table3 where condition3 and obj in (
...
)))

第二个:

select obj from table1 where condition1
and obj in (select obj from table2 where condition2)
and obj in (select obj from table3 where condition3)
...

第三个:

select table1.obj from table1
inner join table2 on table2.obj = table1.obj and table2.condition='condition2'
inner join table3 on table3.obj = table2.obj and table3.condition='condition3'
...
where table1.condition='condition1'

我的问题是,如果这些查询提供相同的结果,并且这些查询同样是最佳的。

我很确定前两个查询产生相同的输出,但第二个查询更快。我不确定第三个查询。

ADDED

还有另一种选择:

select table1.obj from table1
inner join table2 on table2.obj = table1.obj
inner join table3 on table3.obj = table2.obj
...
where
table1.condition='condition1' and 
table2.condition='condition2' and 
table3.condition='condition3'

4 个答案:

答案 0 :(得分:1)

虽然总有例外,但选项3几乎肯定是最佳/首选。根据您的索引和数据分布,MySQL查询执行计划程序将处理从表中提取的顺序。

在其他情况下,子查询(选项1和2)是针对外部查询的每一行执行的 - 它们可能非常低效。因此,遵循前面的语句,嵌套子查询(选项1)可能比使用一阶子查询(选项2)或普通连接(选项3)指数级更差。

请注意,对于INNER JOIN s,如果额外条件位于JOIN子句或{{1}中,则与性能功能无关条款。因此,您的其他选项实际上等同于选项3。

答案 1 :(得分:1)

基本执行查询的方式如下:FROM(获取整个数据)=> WHERE(应用约束)=> SELECT(显示结果)

JOIN子句始终是连接数据的最佳选择,因为在WHERE子句中,只测试与JOIN子句匹配的数据。

在FROM中,在获取WHERE和SELECT的整个数据之前,选择并测试ON子句中的仅字段。

在前两个示例中,对于每个SELECT,选择表的全部内容以用于WHERE子句的测试。 加入WHERE子句几乎是同样的问题。

最后两个例子似乎都是一样的。我更喜欢最后一个,因为在第三个例子中使用ON子句对于RIGHT或LEFT JOIN是有用的,但在这种情况下,它只会在子句中使用:FROM:获取准确的资源,WHERE:应用约束

这个解释非常示意,但我希望它有意义......

答案 2 :(得分:0)

我怀疑第三个查询会是最快的。 SQL经过优化,可以使JOIN快速运行。

但了解您的数据的唯一方法是尝试并查看。

答案 3 :(得分:0)

首先,这些查询不一定会返回相同的结果:

1. SELECT x FROM table1 WHERE x IN (SELECT x FROM table2 WHERE y = foo)

2. SELECT x FROM table1 JOIN table 2 USING x WHERE table2.y = foo

IN()删除重复项。因此,如果table2包含50个满足条件y = foo的x值,则查询2将返回比查询1多50倍的行。这可能是您想要的或不是。如果两个表中的x都是UNIQUE,则查询将给出相同的结果。

  

子查询(选项1和2)对外部查询的每一行执行

这当然是错误的,因为子查询不是依赖子查询。无论如何,它将执行一次子查询,并对其进行散列或排序以消除重复(按照IN()的要求),然后使用结果列表执行IN连接。 MySQL直到最近的版本确实为每一行重新执行子查询,现在不再是这种情况了。由于MySQL不进行散列IN连接,因此它可能仍然比JOIN慢得多。