首先 - 这里的永久解决方案是清理您的数据。使用 LTRIM、RTRIM、UPPER、LOWER 等函数会使您的not SARGEable。换句话说,您的查询可能会慢到爬行,因为 SQL Server 不可能在不扫描所有行的情况下从索引中检索您需要的数据。
例如,这个查询写了五次 rtrim(LOWER(Title)):
输入 APPLY + VALUES 内联别名技巧
这是我前段时间为了简化代码而提出的,但后来我发现了一些偶尔的性能优势,我将展示这些优势。首先是一些示例数据:
use tempdb;
go
create table dbo.sometable(someid int identity, somevalue decimal(10,2));
insert dbo.sometable(somevalue) values (100),(1050),(5006),(111),(4);
假设我们有一个查询,它接受一些变量或参数,对它们执行计算并在整个查询中使用该值。请注意下面的案例陈述。
declare @var1 int = 100, @var2 int = 50, @var3 int = 900;
select
someid,
somevalue,
someCalculation =
case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end,
someRank = dense_rank() over (order by
case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end)
from dbo.sometable
where case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end
between 900 and 2000
order by case when @var3 < somevalue then (@var1 / (@var2*2.00))+@var3 else @var3+somevalue end;
我们可以像这样简化这个查询:
select
someid,
somevalue,
someCalculation = i.v,
someRank = dense_rank() over (order by i.v)
from dbo.sometable
cross apply (values
(
case when @var3 < somevalue then (@var1/(@var2*2.00))+@var3 else @var3+somevalue end)
) i(v)
where i.v between 900 and 2000
order by i.v;
每个查询都返回相同的结果。现在执行计划:

我们不仅简化了查询,而且实际上加快了查询速度。在我的原始查询中,优化器必须计算两次相同的值并执行两种排序。使用我的内联别名技巧,我能够删除排序和计算