2010-01-05 48 views
7

我從SQL Server(2005)得到一個奇怪的執行計劃行爲。sql服務器:估計的行數是關閉的

表名:LOG
......包含約1000行

  • ID INT
  • 名稱VARCHAR(50)

查詢:

SELECT * 
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) as Row, 
       ID, Name 
      FROM Log) AS LogWithRowNumbers 
WHERE Row >= 1 
    AND Row <= 2 

它估計數量行數返回爲9(雖然它明顯是2或更少)。
此外,在去除 「和Row < = 2」 將增加約* 5.增加執行時間( 「和Row < = 2」 和 「和行< = 9999999999999」 的行爲相同)

我已經更新統計數據但是,這種行爲仍然很奇怪。添加行< 99999999999將使查詢運行速度更快?爲什麼?

+0

來吧夥計們,這是很容易可再現的。那些DBA天才在你需要他們的時候在哪裏? – Faruz 2010-01-05 12:25:15

+0

@Faruz:我不是DBA。但是,如果沒有任何AND/OR(即ROW = 1),只有一個標準,查詢的執行速度會更快。當'ROW = 1或ROW = 2'時它如何執行,而不是使用'> ='和'<='。它是否在內部爲「Log」表創建索引? – shahkalpesh 2010-01-05 12:40:15

+0

行= 1或行= 2估計58個返回的行... 它不創建內部索引但使用PK索引(ID)。 – Faruz 2010-01-06 05:47:19

回答

6

我不是SQL Server的內部工作/查詢優化過程的專家,但這裏是我的2便士(或者如果您願意的話)。

我相信這是由於在WHERE子句中使用了ROW_NUMBER()值。舉個例子,我創建了一個樣例表,裏面填充了從ID 1到1000(ID作爲主鍵)的1000行,就像你說的那樣。

如果取出ROW_NUMBER(),並以此爲基礎進行ID列本查詢:

Select * FROM 
(
SELECT ID, Name 
FROM Log 
) 
as LogWithRowNumbers 
WHERE ID>=1 and ID<=2 

然後正確顯示的行數爲2 - 作爲實料。

現在,向後工作,在ROW_NUMBER添加到內部SELECT,但留下的WHERE子句的,是象下面這樣:

Select * FROM 
(
SELECT ROW_NUMBER() OVER (ORDER BY ID DESC) AS RowNo, 
ID, Name 
FROM Log 
) 
as LogWithRowNumbers 
WHERE ID>=1 AND ID <=2 

這仍然顯示正確的行數爲2

最後中,設置WHERE子句回使用RowNo作爲被過濾的柱,而不是ID,這是當估計的行計數跳到9.

因此,我相信這是使用ROW_NUMBER()函數的,作爲在作爲c的WHERE子句中過濾澳洲英語。所以我可以想象這是因爲在實際表列上有明顯更好/更準確的統計信息,而不是這個函數生成的值。

我希望這至少能夠提供一個很好的起點,希望會有用!

2

AdaTheDev是正確的。您看到這種行爲的原因是因爲SQL Server在可以在where子句中使用它們之前必須計算表的行號。

這應該是得到同樣結果的更有效的方法:

SELECT TOP(2) ROW_NUMBER() OVER (ORDER BY ID DESC) as Row, 
ID, Name 
FROM Log 
ORDER BY ID DESC 
+0

我明白你的意思,只是它是我做的查詢的一個例子。我通常檢索行1-10,10-20等。問題是,我必須做到沒有「行<999999」,並且花費更多 – Faruz 2010-01-06 06:01:40