使用订单时的动态订单 - 加速

时间:2011-12-13 12:08:37

标签: sql sql-server-2008 row-number

我正在使用行号从存储过程中获取分页结果。

我发现使用动态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]

4 个答案:

答案 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