2011-02-07 10 views
6

Mam procedurę przechowywaną, która robi coś takiego:Czy zastępowanie logiki warunkowej za pomocą instrukcji CASE jest wydajne w języku Transact-SQL?

IF @Param = '1' 
    SELECT HT.HeaderKey, HT.Description, 
      (SELECT SUM(E1) -- E1 is actually a complex expression 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
    FROM HeaderTable HT 
ELSE IF @Param = '2' 
    SELECT HT.HeaderKey, HT.Description, 
      (SELECT SUM(E2) -- E2 is yet another complex expression 
      FROM DetailTable DT INNER JOIN ... -- Here, DetailTable is not 
            INNER JOIN ... -- joined to the same tables 
            INNER JOIN ... -- as in the first case 
      WHERE DT.HeaderKey = HT.HeaderKey) 
    FROM HeaderTable HT 
-- Etc. There are five cases. 

I chciałby zmniejszyć zapytanie do następujących:

SELECT HT.HeaderKey, HT.Description, 
     CASE @Param 
     WHEN '1' 
      (SELECT SUM(E1) 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
     WHEN '2' 
      (SELECT SUM(E2) 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
     -- Etc. 
     ELSE 0 
     END 
FROM HeaderTable HT 

Jednakże, jeśli SQL Server ocenia wszystkie przypadki Niezależnie od tego, który z nich zostanie faktycznie zwrócony, zmodyfikowane zapytanie byłoby rażąco nieefektywne.

Tak więc, chciałbym wiedzieć, czy SQL Server ocenić wszystkie przypadki w CASE oświadczenie, czy tylko pierwszy z nich, który spełnia warunku CASE „s?

+0

+1 na dobre pytanie –

+0

Dzięki, Stephanie. – pyon

Odpowiedz

2

Instrukcja CASE dla serwera SQL, o której mowa w this article, wykorzystuje zwarcie, więc w pokazanym przykładzie nie będzie oceniać wyników każdego możliwego wyniku CASE dla każdego wiersza.
Jednak nadal otrzymasz mniej sprawne zapytanie niż twój obecny format, ponieważ zmusisz wszystkie wyniki do udostępnienia tego samego planu wykonania, który może nie być optymalny. W zależności od różnic między podkwadaniami CASE efekt może być dość znaczący.

+0

Jaki jest jego obecny format wymuszający na każdym zapytaniu udostępnienie tego samego planu? Bieżący format ma osobne zapytania. Każdy ma gdzieś jakąś różnicę, jeśli tak nie jest, dlaczego tak jest? –

+0

Po prostu doda inną ścieżkę do planu dla każdego wyniku "sprawy". Nie ma żadnego konkretnego powodu, aby myśleć, że dodatkowa ścieżka spowoduje pogorszenie innych części planu. –

+0

Czytasz błędnie moją odpowiedź - jest napisane, że "nadal otrzymasz mniejszą skuteczność niż NIŻSZY format CURRENT". Drugą częścią PO jest ich proponowany format, który jest mniej wydajny niż ich obecny format (choć prawdopodobnie nieco łatwiejszy w utrzymaniu). – MartW

-1

Prawie zawsze uzyskasz szybszy wynik dzięki rozwiązaniu opartemu na zestawie a opartemu na procedurach rozwiązaniu w SQL Server (i wszystkich RDMS).

+0

Jest ustawiony na podstawie. Pyta, który "zestaw" będzie szybszy. –

+0

Jeśli instrukcje nie są ustawione na podstawie SQL Server. – richard

+0

Dobrze, ale po IF, zostanie wykonana instrukcja SQL. "Praca" jest wykonywana w SET ... ocena IF jest mniejsza niż maleńka w porównaniu do sql. Stosujesz prostą maksymę do skrajności. Mówimy, że ustawienie na podstawie jest lepsze, nie oznacza to, że pierwsza linia kodu zabija wydajność. Oznacza to, że nie pętli i przetwarzania tabel wiersz po wierszu. –

0

zakładając, że przyłącza są takie same w każdym podzapytania, chciałbym spróbować czegoś takiego:

;with dt as 
(
    select 
     HeaderKey, 
     sum(case @Param 
      when 1 then E1 
      when 2 then E2 
      ...) as ExpressionSum 
    from DetailTable DT 
     inner join... 
    group by dt.HeaderKey 
) 
select 
    ht.HeaderKey, 
    ht.description, 
    dt.ExpressionSum 
from HeaderTable HT 
    inner join dt 
     on HT.HeaderKey=dt.HeaderKey 

czy mogę być rażąco nieporozumienie co starasz się zrobić;)

+1

"Tutaj DetailTable nie jest połączony z tymi samymi tabelami co w pierwszym przypadku." ZNAJDŹ komentarz. To nie są te same tabele ... –

+0

@stephanie, nie widziałem tego, dzięki – DForck42

+0

Też tęskniłem za ... –

Powiązane problemy