Frage

Im folgenden Beispiel ist die Leistung der ersten Version mit nur einer SQL -Abfrage sehr schlecht. Das Problem ist der letzte Join.

Wenn ich das Ergebnis der linken Seite in einen temporären Tisch speichere und sich diesem anschließt, läuft es etwa 50 -mal schneller.

Es ist beabsichtigt, dies in Oracle umzuwandeln. Daher versuche ich, die Verwendung von temporären Tabellen zu vermeiden.

Irgendwelche Erklärungen, warum sich die erste Abfrage so schlecht verhält oder Hinweis, um sie zu verbessern?

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;

BEARBEITEN:

Hier die Funktion:

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
War es hilfreich?

Lösung

Genau wie erwartet.

Ein Skalar -UDF ist eine schwarze Box für den Optimierer: Es können keine Indizes verwendet werden, die Kosten können nicht richtig ausgearbeitet werden.

Und wenn der Skalar -UDF über einen Tabellenzugriff verfügt, haben Sie einen Cursor (schlecht in SQL Server), um eine Suche durchzuführen pro Zeile: Es ist kein fester Set -basiertes Vorgang

Um es zu beheben, verwenden Sie auf diese Weise keinen UDF. Es kann als Join geschrieben werden. Es gibt keinen Hinweis oder keine Magie

Bearbeiten: Entfernen Sie die UDF. Für jede Zeile in Bewertungen Ihre Abfrage fähigitungen. Es ist exponentiell

Und ich bewegte die Filter in die Verknüpfungen

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top