2010-06-08 69 views
1

我正在運行兩個非常相似的更新查詢,但由於我未知的原因,他們正在使用完全不同的執行計劃。通常這不會是一個問題,但他們都更新完全相同數量的行,但一個正在使用的執行計劃,遠遠低於其他,4秒比2分鐘,當擴大這導致我一個大問題。針對類似查詢的不同執行計劃

兩個查詢之間唯一的區別是一個是使用列CLI和另一個DLI。這些列是完全相同的數據類型,並且兩者的索引完全相同,但對於DLI查詢執行計劃,不使用索引。

任何有關爲什麼發生這種情況的幫助非常感謝。

-- Query 1 
UPDATE a 
SET DestKey = ( 
SELECT TOP 1 b.PrefixKey 
FROM refPrefixDetail AS b 
WHERE a.DLI LIKE b.Prefix + '%' 
ORDER BY len(b.Prefix) DESC) 
FROM CallData AS a 

-- Query 2 
UPDATE a 
SET DestKey = ( 
SELECT TOP 1 b.PrefixKey 
FROM refPrefixDetail b 
WHERE a.CLI LIKE b.Prefix + '%' 
ORDER BY len(b.Prefix) DESC) 
FROM CallData AS a 

回答

3

檢查表上這兩列的統計信息(如何在所有行中分配列的數據值)。這將可能解釋差異......其中一列可能有一個值分佈,可能會導致查詢在處理過程中需要檢查的行數比另一個查詢所需要的要多得多(數字或更新的行由頂部1部分控制),那麼查詢優化器可能會選擇不使用索引...更新統計信息將使它們更加準確,但是如果值的分佈是這樣的,以致優化器選擇不要使用索引,那麼你可能會運氣不佳...

瞭解索引如何工作在這裏很有用。索引是節點的樹狀結構,其中每個節點(從根節點開始)包含的信息允許查詢處理器根據它正在「搜索」的值來確定要去哪個樹的哪個分支。它類似於二叉樹,只是在數據庫中樹不是二進制的,在每個層次上,每個節點下可能有多於2個分支。

因此,對索引來說,要遍歷索引,從根到葉級,要求處理器爲索引hiearchy中的每個級別讀取索引一次。 (例如,如果索引是5級深度,則需要對其搜索的每個記錄執行5次I/O操作。

因此,在本例中,如果查詢需要檢查超過大約20%表中的記錄(基於您正在搜索的列的值分佈),那麼查詢優化器會對自己說自己,找到20%的記錄,每個記錄有5個I/O搜索,等於讀取整個表的相同數量的I/O「,所以它只是忽略索引並進行表掃描。

除了通過添加附加條件到您的查詢以進一步限制查詢必須檢查的記錄數以生成結果....

+0

感謝您的及時響應 我已經檢查了這兩個指標的統計數據,我不確定我在這裏尋找什麼,有什麼建議嗎?有一些不同之處。有什麼我可以做的例如,有沒有什麼辦法可以強制優化器使用索引,因爲它似乎正在採用的路線的效率要低得多。如果索引不能改進我的查詢,似乎毫無意義的索引 – 2010-06-08 15:18:14

+0

瞭解索引如何工作在這裏是有用的。我正在編輯我的答案添加此.... – 2010-06-08 15:57:17

+0

感謝您的解釋,這當然幫助我理解爲什麼會發生這種情況。不幸的是,我無法進一步限制結果,所以我想我必須忍受這一點,因爲從你所說的事實上來看,它實際上是最有效的方式。 – 2010-06-09 13:42:32

1

嘗試更新您的統計信息。如果這沒有幫助重建索引。每列中數據的基數可能很不相同,從而導致選擇不同的執行計劃。

+0

我已刪除我的索引並重新創建,我已重建索引,更新統計信息並截斷並重新插入數據。這些都不會對查詢執行計劃產生任何影響。 :-( – 2010-06-08 15:19:24