在下面的示例中,仅使用一个SQL查询的第一个版本的性能非常糟糕。问题是最后一个加入。

当我将左侧的结果存储到临时表中并加入此功能时,它的运行速度约为50倍。

它旨在将其转换为Oracle,因此我尝试避免使用临时表。

有任何解释,为什么第一个查询行为如此糟糕或提示改善它?

Declare @HO int = 2866;
Declare @Dtz int = 35;

---- version 1 takes about 60 seconds
With ratings as
(
    select
        ROW_NUMBER() Over ( ORDER BY SEDate) lfd, 
        SEDate, 
        BBCode 
    from  PPV
        join BB on BBRefnr = SEBBRefnr
    where SEHORefnr = @HORefnr 
    and SEBBRefnr > 0
)
Select
    SEDATE,
    BBCODE,
    Code,
    DTRefnr
FROM (  
Select 
    l.SEDate,
    l.BBCode,
    dbo.GetCode(@Dtz, l.BBCode) Code
from ratings l left join ratings r on l.lfd = r.lfd + 1
where l.BBCode <> r.BBCode
or r.BBCode is null
) as t
    join DT d on code = d.DTCode and d.DTDTKRefnr = @Dtz 
order by 1;

------- version 2 using a temp table takes less than 1 second

With ratings as
(
    select
        ROW_NUMBER() Over ( ORDER BY SEDate) lfd, 
        SEDate, 
        BBCode 
    from  PPV
        join BB on BBRefnr = SEBBRefnr
    where SEHORefnr = @HORefnr 
    and SEBBRefnr > 0
)
Select 
    l.SEDate,
    l.BBCode,
    dbo.GetCode(@Dtz, l.BBCode) Code
into #tmp
from ratings l left join ratings r on l.lfd = r.lfd + 1
where l.BBCode <> r.BBCode
or r.BBCode is null


Select
    SEDATE,
    BBCODE,
    Code,
    DTRefnr
FROM #tmp
    join DT d on code = d.DTCode and d.DTDTKRefnr = @Dtz 
order by 1;

编辑:

这里的功能:

Create function dbo.GetCode (
    @fDtz int, 
    @Value varchar(10)
) returns varchar(10)
as
begin
    declare @CODE varchar(10)
    SET @Code =
        (SELECT Code FROM Ableitungen 
        WHERE DTZ = @fDtz
        AND Value = @Value )

    return @CODE
end
有帮助吗?

解决方案

完全如预期的那样。

标量UDF是优化器的黑匣子:不使用索引,成本无法正确处理。

而且,如果标量UDF具有表访问权限,则您可以运行光标(SQL Server中的不良)来进行查找 每行: :这不是基于集合的操作

要修复它,请不要以这种方式使用UDF。它可以写作加入。没有提示或魔术

编辑:删除UDF。对于评分中的每一行,您的查询能力。这是指数的

而且我将过滤器移至连接

With ratings as
(
    select
        ROW_NUMBER() Over (ORDER BY SEDate) lfd, 
        SEDate, 
        BBCode 
    from  PPV
        join BB on BBRefnr = SEBBRefnr
    where SEHORefnr = @HORefnr 
    and SEBBRefnr > 0
)
Select 
    l.SEDate,
    l.BBCode,
    A.Code,
    D.DTRefnr
from 
    ratings l
    left join 
    ratings r on l.lfd = r.lfd + 1
    JOIN 
    Ableitungen A ON A.Value = l.BBCode
    join
    DT d on A.code = d.DTCode and d.DTDTKRefnr = A.DTZ
where
    A.DTZ = @fDtz
    AND 
   (l.BBCode <> r.BBCode or r.BBCode is null)
order by
    SEDATE;
许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top