2013-12-11 36 views
1

我阅读此页有关适用于:WHERE和ON子句执行的顺序是什么?

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/07/07/using-cross-apply-to-optimize-joins-on-between-conditions.aspx

和我读到这篇文章的逻辑查询处理:

http://blog.sqlauthority.com/2009/04/06/sql-server-logical-query-processing-phases-order-of-statement-execution/

所以我能理解这个查询如何需要很长的时间。

SELECT s.StartedAt, s.EndedAt, c.AirTime 
FROM dbo.Commercials s JOIN dbo.Calls c 
    ON c.AirTime >= s.StartedAt AND c.AirTime < s.EndedAt 
WHERE c.AirTime BETWEEN '20080701' AND '20080701 03:00' 

的加盟经历的所有行,然后 WHERE子句对结果进行过滤。

但为什么这个查询闪电般快?

SELECT s.StartedAt, s.EndedAt, c.AirTime 
FROM dbo.Commercials s JOIN dbo.Calls c 
    ON c.AirTime >= s.StartedAt AND c.AirTime < s.EndedAt 
WHERE c.AirTime BETWEEN '20080701' AND '20080701 03:00' 
AND s.StartedAt BETWEEN '20080630 23:45' AND '20080701 03:00' 

我得到的是WHERE子句过滤两个表的结果。但 JOIN之后发生过滤发生,而不是之前它。现在,如果它以某种方式实际发生在JOIN之前,那么我肯定明白它为什么如此之快。但是,如果我在第二环节通过LOE,情况不应该如此。对?

+0

我们可以选择表结构吗?如果查询速度非常快,那么最可能的索引是最优的。小一些。如果没有表格定义,很难确定。 –

+0

您需要查看解释以查看优化器在做什么。由于您的连接是内部连接,因此优化器很可能会重新编写您的查询。 – Andrew

+0

您检查了执行计划吗?你应该看看关于sql server enginer和optimizer的文章。我认为它总是会尝试执行第一个index_seek,然后table_scan,据我所知,如果您正在基于索引和连接子句基于非索引列运行where子句,它将首先执行where子句。嗯再读你的查询,我会说优化器做了一个很好的工作,你没有平等但>和所以它首先减少2临时表,然后加入他们比较值。这对我来说似乎是正确的 –

回答

0

大量的逻辑,时间,血液,汗水和泪水都进入了SQL Server Engine Optimizer,这就决定了查询计划决定了如何处理语句。在声明中写入的内容绝不反映在引擎中实际执行的内容。

要真正了解发生了什么,请启用显示实际查询计划选项来运行查询。我的猜测是,基于额外的where子句,数据被优化器预过滤。

1

这些查询没有明确的“之前”和“之后”。只要查询产生的结果不会改变,RDBMS就可以决定何时运行查询的哪一部分。

在第一种情况下,查询无法对Commercials行进行预过滤,因为WHERE子句仅限制Calls的行。这些约束条件规定了c.AirTime的范围,因为相应的行为Commercials,所以不需要进行预过滤:对于Commercials的每一行,将考虑Calls的所有行。

然而,在第二种情况下,RDBMS可以通过观察到您将范围c.AirTime限制在2008年6月30日至2008年7月1日午夜的23:45之间,通过将s.StartedAt限制为其中c.AirTime已加入。这可以允许优化器使用索引(如果在Calls.AirTime列中定义了索引)。

这里的重要观察是,在优化查询时,RDBMS可以做出非常聪明的事情。它通过应用多个逻辑规则来达到优化策略,试图将约束推向更接近连接中“行的源”的位置。检查优化器做什么的最佳选择是阅读查询计划。

0

他们是不一样的查询,为什么你会想到同样的响应时间

如果两个查询返回不同的行数,然后用顶X一个更公平的比较

查询优化可以得到非常聪明(它可以让人变得愚蠢)
查看查询计划,看看到底是怎么回事

我的经验是查询优化具有越来越聪明的一个更好的机会,如果你拉的条件为加盟

SELECT s.StartedAt, s.EndedAt, c.AirTime 
FROM dbo.Commercials s 
JOIN dbo.Calls c 
    ON c.AirTime >= s.StartedAt 
    AND c.AirTime < s.EndedAt 
    AND c.AirTime BETWEEN '20080701' AND '20080701 03:00' 
    AND s.StartedAt BETWEEN '20080630 23:45' AND '20080701 03:00' 

如果你只是有一个连接,然后查询优化器可以移动,其中早期
但是,如果你有多个连接我从来没有见过的查询优化移动一个地方

0

第二个查询更快为什么你要限制连接的范围。

首先查询:A JOIN B

第二个查询:一个加入集B

由于集B <乙本身也有少了很多扫描匹配。

而这会导致一个问题:该连接中使用的列是否有索引? (可能不是或速度不能很大不同)

相关问题