2013-12-11 73 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 <乙本身也有少了很多掃描匹配。

而這會導致一個問題:該連接中使用的列是否有索引? (可能不是或速度不能很大不同)

相關問題