我正在使用行号从存储过程中获取分页结果。
我发现使用动态case语句列名称进行排序会降低速度 - 但如果我按顺序硬编码顺序就行了。
有没有办法加快动态订单,而不使WHOLE sql查询一个字符串并使用SP_EXECUTESQL
ROW_NUMBER() OVER (ORDER BY
CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 0 THEN CLH.IdentityValue END DESC,
CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 1 THEN CLH.IdentityValue END
--CLH.CustomerName
) AS [ROW]
答案 0 :(得分:1)
问题是SQL Server正在尝试构建一个适合所有参数的执行计划。这意味着当你给它不同的参数时,它不会改变它的想法并选择不同的索引。 (different index
部分很重要,因为重新排序不合适的索引的负担可能非常高。)
实现这一目标的唯一方法是生成一个新的执行计划,这涉及动态SQL - 正是您想要避免的。
然而;动态SQL和SP_EXECUTESQL不一定是个坏主意。由于它也可以进行参数化,正确使用确实可以重复使用执行计划,并且在这些问题上可以非常有效。
是否有特殊原因需要避免动态SQL?
唯一可行的解决方法是使用不同的顺序多次写出查询,并选择与T-SQL IF
块一起使用的查询。这将允许优化器生成不同的执行计划。
答案 1 :(得分:1)
SQL Server不支持单个查询根据参数值使用不同的索引。 AFAIK,有两种解决方案:
sp_executesql
实际上,PHP和.NET应用程序很难共享代码。甚至是不同的.NET版本。这使得第一种选择成为更有选择的选择。
所以最好的方法是动态SQL。是的,这是非常令人惊讶的。 :)
答案 2 :(得分:0)
您可以尝试的一件事是将您的两个案例条款合并为一个案例 - 如下所示:
(ORDER BY
CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 0
THEN CLH.IdentityValue*-1
WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 1
THEN CLH.IdentityValue
END
)
显然,如果你的一些潜在排序值是字符串而不是数字,这种方法就不实用了。
答案 3 :(得分:0)
尝试使用多个ROW_NUMBER语句,这样每个排序的处理次数就会减少
ROW_NUMBER() OVER (ORDER BY CLH.IdentityValue) DESC AS rnDesc,
ROW_NUMBER() OVER (ORDER BY CLH.IdentityValue) AS rnAscDesc,
...
ORDER BY
CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 0 THEN rnDesc END,
CASE WHEN @OrderByColumnName = 'IdentityValue' AND @OrderAscending = 1 THEN rnDesc END