我在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
答案 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执行它。因此,每个输入参数都会获得它自己的执行计划,而不是整个过程中只有一个。每次执行都使用正确的索引。