提高在where子句中使用isnull的性能

时间:2012-10-16 16:08:55

标签: sql-server reporting-services

有一个报告,其查询在where子句中使用isnull,这会导致一些性能问题。 这是一个非常简单的例子。 http://www.sqlfiddle.com/#!6/79759/11

查询使用多值参数,通常只返回一个或两个值。 (我试图使用sqlfiddle中的表变量复制SSRS多值参数)

select 
  isnull(descrL,descr) as division,
  product
from Upper
left join Lower on product = productL
where isnull(DescrL,Descr) in (@params)

有一个上级部门拥有所有产品。有些产品存在于儿童部门。如果它存在于较低的分区中,那就是应该显示的分区。

公司参数可以接受上级,下级或两者。

有关如何更改查询以获得更佳性能的任何想法?

2 个答案:

答案 0 :(得分:2)

select  descrL as division, product
from Lower 
where DescrL like @params + '%'
union
Select descr, product
from Upper
where Descr like @params = '%'

这将是非常高效的。如果在顶部选择中找到匹配,则应在底部选择中对其进行抑制,因为它是联合而不是联合全部。请注意,而不是in。如果你执行in,那么就无法使用DescrL或Descr上的索引来查找结果。如果你这样做,索引就可以了。您可能必须调整应用程序逻辑才能使其工作。

如果你不能这样做,那就有这个解决方案。您必须将fn_split添加到您的数据库。 http://msdn.microsoft.com/en-us/library/aa496058(v=sql.80).aspx

    select  descrL as division, product
    from Lower l 
    join dbo.fn_Split(@params, ',') p1
        on l.DescrL = p1.value
    union
    Select descr, product
    from Upper u 
    join dbo.fn_Split(@params, ',') p2
        on u.Descr = p2.value

如果你真的想要完成性能的最后一点,你可以声明一个表变量,只运行fn_split一次以填充表变量,然后使两个连接成为表变量。所以在这里你也可以利用列上的索引,这是使查询更快的主要内容。当你运行它时,总是在sql server中“包含实际的执行计划”,并查看结果并确保你看到的是索引而不是表扫描。

编辑:我去了你的sqlfiddle链接。没有早点看到它。这有效。工会本身不会压制欺骗,因为你也选择了部门,对不起。因此,您必须使用not in或者我更喜欢左侧外部null。

select descrL as division, productL as product
    from Lower l 
    join @params p1
        on l.DescrL = p1.division
    union
    Select u.descr, u.product
    from Upper u 
    join @params p2
        on u.Descr = p2.division
    left join (select productL as product
                from Lower l2 
               join @params p3
                 on l2.DescrL = p3.division) sub1
     on u.product = sub1.product
        where sub1.product is null
order by 2

答案 1 :(得分:1)

我不确定,但是在你的情况下会有效吗?

;with BothDivs as
(
  select 
  isnull(descrL,descr) as division,
  product
  from Upper
  left join Lower on product = productL
)
select division, product
from BothDivs
where division in (@params)