2013-01-11 57 views
1

我們有一個視圖用於通過聚簇索引在表中查找記錄。該視圖在select語句中還有幾個子查詢,這些子查詢在兩個大表中查找數據,也通過聚簇索引進行查找。SQL Server 2005緩存了一個永遠無法運行的執行計劃

爲了簡化巨大,將是這樣的:

SELECT a, 
(SELECT b FROM tableB where tableB.a=tableA.a) as b 
(SELECT c FROM tableC where tableC.a=tableA.a) as c 
FROM tableA 

大多數查找到[tableB的]正確使用上[tableB的]一個非聚集索引,非常有效的工作。但是,偶爾SQL Server在生成執行計劃時,會在[tableB]上使用一個不包含要傳遞的值的索引。因此,按照上面的示例,儘管tableB上存在列[a]的索引,但該計劃會掃描具有列[z]的聚集索引。使用SQL自己的語言,計劃的「謂詞與對象無關」。我不明白爲什麼這將是實用的。因此,當SQL執行此操作時,它必須掃描索引中的每條記錄,因爲它永遠不會存在,最多需要30秒。它總是顯而易見的錯誤。

有沒有人看過這個之前,執行計劃做的東西看起來像它永遠不會是正確的?無論如何,我將重寫查詢,因此我關心的不是查詢結構,而是更多的是爲什麼SQL會讓它錯誤。

我知道有時候SQL Server可以選擇一種曾經工作過的計劃,並且隨着數據集的變化它可能變得效率低下,但在這種情況下,它可能永遠不會工作。

更多信息

  • [tableB的]有4萬條記錄,併爲大多數值[A]是空
  • 我現在無法獲得生成該計劃的初始查詢的保持
  • 這些查詢都是通過ColdFusion的運行,但在這個時候,我很感興趣,有人見過這個獨立的SQL Server

回答

3

這似乎總是錯的。

您可能會感興趣的First Rule of Programming

所以,按照上述實施例,雖然並[a]存在tableB的列的索引 ,計劃,而不是不具有柱[Z]聚簇索引 的掃描。

聚集索引始終包含所有行。它可能會按z排序,但它仍將包含葉級別的所有其他列。

SQL Server有時偏好索引查找的集羣掃描的原因是這樣的。當您執行索引查找時,必須通過書籤查找聚集索引來檢索不在索引中的列。

當您執行聚簇索引掃描時,您將按照定義查找所有列。這意味着不需要書籤查找。

當SQL Server期望很多行時,它會嘗試避免書籤查找。這是一個經過時間考驗的選擇。非聚簇索引查找通常通過聚簇索引掃描進行打擊。

您可以通過強制使用with (index(IX_YourIndex)) query hint來測試您的情況。

+0

非常好。非常感謝。我希望有更多知識的人會告訴我我的假設出錯了。我的問題是故意挑釁。我花了許多小時追蹤原始錯誤報告,然後試圖責怪自己,但看不到答案。 – Raspin