CASE语句需要很长时间

时间:2014-11-29 01:02:41

标签: sql sql-server performance

我在SELECT查询中添加了CASE ... WHEN语句,导致查询运行时间延长了25秒

对于为什么有任何想法?

这是原始查询大约需要7-8秒(即没有CASE语句)

注意:我通过添加一些硬编码值来简化查询,以便将代码的焦点吸引到上面列出的麻烦点

select * from (
    select
        (row_number() over (
              order by b.BookTitle
            ))
        as RowNumber,
        b.*
    from
        Books b 
) as t1
where 
    RowNumber between 40 and 60
order by
    RowNumber

现在,这里是CASE语句(注意:case语句用于确定如何排序结果)

declare @SortByField nvarchar(255)
select @SortByField = NULL

select * from (
    select
        case @SortByField
          when 'Published' then 
            (row_number() over (
              order by b.PublishDate, b.BookTitle
            ))
          when 'Price' then 
            (row_number() over (
              order by b.RetailPrice, b.BookTitle
            ))
          when 'Author' then
            (row_number() over (
              order by b.AuthorName desc, b.BookTitle
            ))
          when 'Sold' then
            (row_number() over (
              order by b.ItemsSold desc, b.BookTitle
            ))
          else
            -- Notice in the first line of code for this snippet that @SortByField is
            -- set to NULL? So this condition should evaluate yet it still takes significantly longer
            (row_number() over (
              order by b.BookTitle
            ))
        end as RowNumber,
        b.*
    from
        Books b 
) as t1
where 
    RowNumber between 40 and 60
order by
    RowNumber

2 个答案:

答案 0 :(得分:2)

好吧,它必须运行所有row_numbers(),这显然需要一些时间。请尝试使用此子查询:

from (select row_number() over (order by (case when @SortByField = 'Published' then PublishDate end),
                                         (case when @SortByField = 'Price' then Price end),
                                         (case when @SortByField = 'Author' then Author end),
                                         (case when @SortByField = 'Sold' then Sold end),
                                         BookTitle
                               ) as RowNumber,
             b.*
      from Books b 
     ) b

这看起来可能是相同的逻辑,但它只调用row_number()一次 - row_number()通常比case更贵,所以只调用一次应该是改善。

答案 1 :(得分:1)

第一个查询可能会使用BookTitle列上的索引,因此数据已按顺序排列。 但是第二个问题是什么?

我认为它首先要评估所有行的case块然后进行排序。 你有没有检查执行计划?

我会尝试根据给定的参数@SortByField动态构建过程中的sql语句,然后使用sp_executesql执行它。因此,每个输入参数都会获得它自己的执行计划,而不是整个过程中只有一个。每次执行都使用正确的索引。