2009-09-11 58 views
0

比方說,我們有
SELECT * FROM A INNER JOIN B ON [....] 內連接與連接表,其中

假設A有兩行和B包含1M行包括2行鏈接到A
B將只有一次與「實際掃描2行右側的「#行」?

如果我在表B添加WHERE
SELECT * FROM A INNER JOIN B ON [....] WHERE B.Xyz > 10

WHERE實際上在加入之前執行......所以,如果在那裏 返回1000行,在中B「行的實際#」將1000 ... 我不明白它..不應該是< = 2 ???

我在想什麼......爲什麼優化器會以這種方式進行? (SQL 2008)

感謝

+0

我認爲這是因爲表A包含比B更多的行..有可能嗎?我沒有提到A有很多行,我在其上做了一個WHERE – 2009-09-11 16:43:26

回答

2

優化器將進行它認爲無論怎樣比較快。這意味着如果Xyz列被索引但連接列不是,它可能會首先執行xyz過濾器。或者如果你的統計信息不好,所以它不知道聯接過濾器會將B減少到兩行,它會首先執行WHERE子句。

1

它完全基於哪些索引可供優化器使用。另外,沒有理由相信數據庫引擎會在查詢的另一部分之前執行WHERE。只要返回正確的結果,查詢優化器可以按照它喜歡的任何順序自由執行查詢。同樣,正確優化這種類型查詢的方法是使用戰略性放置索引。

0

「僅掃描一次」有點誤導。在SQL Server中,表掃描是一件非常昂貴的事情。至少在SS2005中,表掃描需要將所有行讀入臨時表,然後讀取臨時表以查找與連接條件匹配的行。因此,在最壞的情況下,您的查詢將讀取並寫入 1M行,然後嘗試將2行與1M行匹配,然後刪除臨時表(最後一位可能是查詢中最便宜的部分)。因此,如果B上沒有可用的索引,那麼你只是處於一個不好的地方。

在第二個例子中,如果B.Xyz沒有編制索引,則全表掃描發生在之間,存在從2行到1000行的輔助匹配 - 效率更低。如果B.Xyz 編制索引,則應該有索引查找和2:1000匹配 - 更快的效率更快。

'當然,這裏假定表的統計信息是相對最新的,沒有任何選項可以改變優化器的工作方式。

編輯:是否有可能「展開」A行並將它們用作B上的no-JOIN查詢中的靜態條件?我們已經在我們的應用程序中的幾個地方使用了這個功能,我們正在將小表(< 100行)加入大型(> 100M行),效果很好。