2014-02-20 95 views
3

平臺 - SQL Server 2008 R2的 這是一個複雜的存儲過程的一部分,正在採取超過5分鐘來執行,我被要求幫助解決行爲CTE子查詢的

;WITH FilteredOrders AS 
    (
     --CTE definition 
    ), 
    PagedOrders AS  
    ( 
     SELECT * FROM  
     ( 
     SELECT ROW_NUMBER() OVER (order by OrderNumber asc) AS Row, 
     --Column List from FilteredOrders 
     FROM FilteredOrders  
    ) AS NumberedOrders  
     WHERE NumberedOrders.Row BETWEEN 1 AND 500 
    ) 
SELECT * FROM PagedOrders 

我消除了第二個CTE中的子查詢並推薦此

;WITH FilteredOrders AS 
    (
     --CTE definition 
    ) 
    SELECT ROW_NUMBER() OVER (order by OrderNumber asc) AS Row, 
    --Column List from FilteredOrders 
    INTO #PagedOrders 
    FROM FilteredOrders 

SELECT * 
FROM #PagedOrders 
WHERE #PagedOrders.Row BETWEEN 1 AND 500 

現在查詢在2秒內執行。雖然我討厭承認它,但事實是,我並不完全理解第二個查詢給出的巨大性能收益。爲什麼我看到如此多的差異?

+0

可能與實體化? http://stackoverflow.com/a/1531994/314291 – StuartLC

+0

對不起,我不同意你的第二個查詢是巨大的性能增益,而不是first.why你不要把row_number內FilteredOrders然後不需要PagedOrders。 – KumarHarsh

回答

0

我相信CTE的查詢在每次調用時都會被評估。這與觀點相似。但是,將數據插入散列表時,將其一次性過程避免多次執行。

這與建議使用索引視圖的原因相同,因爲數據實際上是物理存儲的而在運行時未進行評估。 CTE和哈希表也會出現同樣的情況。

出於同樣的原因,CTE也可以在連接中避免,直到您確定CTE查詢足夠快以至於不影響性能。

0

方法1,但有多少行,包括在首位

WITH FilteredOrders AS 
    (
     select blah,blah, ROW_NUMBER() OVER (order by OrderNumber asc) AS Row 
from blah 
    ), 

     select * FROM FilteredOrders Row BETWEEN 1 AND 500 

方法2,

SELECT blah,blah, ROW_NUMBER() OVER (order by OrderNumber asc) AS Row, 
    --Column List from FilteredOrders 
    INTO #PagedOrders 
    FROM [use join logic of FilteredOrders here ]