2014-02-20 56 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 ]