多年来,我一直在通过将ROW_NUMBER
()包装到CTE中来创建动态sql分页。这种方法在stackoverflow中已经多次提及,并且它提供了良好的性能。
但是,由于sql server 2012引入了offset
和fetch
,性能更好,我决定看看我是否可以优化我的sql 2008 R2分页语句以匹配sql server 2012的性能。
这个blog entry描述了offset
命令的一个非常有趣的替代方法:
WITH cteKeySeek
AS
(
SELECT
BusinessEntityID,
LastName,
ROW_NUMBER() OVER (ORDER BY LastName,BusinessEntityID)-1 AS RowN
FROM Person.Person
)
SELECT
TOP(20) cteKeySeek.LastName,
FirstName,
cteKeySeek.BusinessEntityID,
RowN
FROM cteKeySeek
INNER LOOP JOIN Person.Person
ON cteKeySeek.BusinessEntityID = Person.BusinessEntityID
WHERE RowN >= 20 AND RowN<=39
ORDER BY LastName,BusinessEntityID;
但是,上面提到的这个替代方法是使用索引表,而我需要的是动态sql。我尝试了几种方法为动态sql语句创建类似的实现但没有成功......性能比常规CTE / ROW_NUMBERS方法慢10倍。
这是迄今为止我可以创建的最佳实现:
WITH T1 AS ( << Your Dynamic SQL here >> )
SELECT TOP 100 T2.RowN , T2.*
FROM (
SELECT ROW_NUMBER() OVER ( ORDER BY WhateverField ) AS RowN, WhateverID, WhateverField
FROM T1
) AS T2
INNER LOOP JOIN T1 ON T2.WhateverID = T1.WhateverID
WHERE T2.RowN BETWEEN 10000 AND 10999
ORDER BY WhateverField;
理想情况下,我更喜欢只涉及动态sql的解决方案......我知道有时存储过程可能会提供其他替代方案,但如果我必须在管理SP和迁移到SQL 2012之间做出选择,我会选择第二种选择。