我正在阅读此页面关于APPLY:
我读了这篇关于逻辑查询处理的文章:
所以我可以理解这个查询需要很长时间。
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 :(得分:1)
这些查询没有明确的“之前”和“之后”。允许RDBMS决定何时运行查询的哪个部分,只要查询产生的结果不会改变。
在第一种情况下,查询无法预先过滤Commercials
行,因为WHERE
子句仅限制Calls
的行。这些约束根据c.AirTime
的相应行指定Commercials
的范围,因此不可能进行预过滤:Calls
的所有行都将考虑{{1}的每一行}}
然而,在第二种情况下,RDBMS可以通过观察您在2008年6月30日到2008年7月1日午夜之间将Commercials
的范围限制在23:45之间来改善时间。限制c.AirTime
加入s.StartedAt
的{{1}}。这可以允许优化器使用索引(如果在c.AirTime
列上定义了索引。
这里重要的观察是,在优化查询时,RDBMS可以做很聪明的事情。它通过应用多个逻辑规则来实现优化策略,尝试将约束推向更接近连接中的“行源”。检查优化器执行操作的最佳选择是读取查询计划。
答案 1 :(得分:0)
SQL Server Engine Optimizer中存在大量的逻辑,时间,血液,汗水和眼泪,这决定了确定语句实际处理方式的查询计划。在声明中写的内容绝不反映引擎中实际执行的内容。
要真正了解正在发生的情况,请启用show actual query plan选项运行查询。我的猜测是,基于额外的where子句,数据被优化器预过滤。
答案 2 :(得分:0)
它们不是相同的查询,所以为什么你会期望相同的响应时间
如果两个查询返回的行数不同,则使用top 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'
如果您只有一个连接,那么查询优化器可能会提前移动到哪里 但是如果你有多个连接,我从未见过查询优化器提前移动
答案 3 :(得分:0)
第二个查询更快地限制了连接的范围。
第一个查询:加入B
第二个查询:连接子集(B)
作为子集(B)&lt; B本身扫描的匹配要少得多。
这导致了一个问题:该连接中使用的列有一个索引? (可能不是或速度不能相差很多)