Wydajność zastosowania zewnętrznego vs łączenie w lewo

37

Używam SQL SERVER 2008 R2

Właśnie natrafiłem na ZASTOSUJ w SQL i podobało mi się, jak rozwiązuje problemy z zapytaniami w tak wielu przypadkach,

W wielu stołach, w których używałem 2 lewych złączeń, aby uzyskać wynik, udało mi się uzyskać 1 zewnętrzną aplikację.

Mam małą ilość danych w moich lokalnych tabelach DB i po wdrożeniu kod powinien działać na danych co najmniej 20 razy większy.

Obawiam się, że zastosowanie zewnętrzne może potrwać dłużej niż 2 warunki dołączenia po lewej dla dużej ilości danych,

Czy ktoś może powiedzieć, jak dokładnie działa zastosowanie i jak wpłynie to na wydajność w bardzo dużych danych, Jeśli to możliwe, pewne proporcjonalne relacje z wielkością każdej tabeli, takie jak proporcjonalne do n1 ^ 1 lub n1 ^ 2 ... gdzie n1 jest liczbą wierszy w tabeli 1.

Oto zapytanie z 2 pozostałymi złączeniami

select EC.*,DPD.* from Table1 eC left join
  (
   select member_id,parent_gid,child_gid,LOB,group_gid,MAX(table2_sid) mdsid from Table2
   group by member_id,parent_gid,child_gid,LOB,group_gid

  ) DPD2 on DPD2.parent_gid = Ec.parent_gid
        AND DPD2.child_gid = EC.child_gid
        AND DPD2.member_id = EC.member_id
        AND DPD2.LOB = EC.default_lob
        AND DPD2.group_gid = EC.group_gid
  left join
  Table2 dpd on dpd.parent_gid = dpd2.parent_gid 
            and dpd.child_gid = dpd2.child_gid
            and dpd.member_id = dpd2.member_id 
            and dpd.group_gid = dpd2.group_gid 
            and dpd.LOB = dpd2.LOB
            and dpd.table2_sid = dpd2.mdsid

Oto zapytanie z zewnętrznym zastosowaniem

select * from Table1 ec   
OUTER APPLY (
      select top 1 grace_begin_date,retroactive_begin_date,Isretroactive
                    from Table2 DPD 
                    where DPD.parent_gid = Ec.parent_gid
                    AND DPD.child_gid = EC.child_gid
                    AND DPD.member_id = EC.member_id
                    AND DPD.LOB = EC.default_lob
                    AND DPD.group_gid = EC.group_gid
                    order by DPD.table2_sid desc
     ) DPD 
Pratyush Dhanuka
źródło

Odpowiedzi:

44

Czy ktoś może powiedzieć, jak dokładnie działa zastosowanie i jak wpłynie na wydajność w bardzo dużych danych

APPLYjest połączeniem skorelowanym (zwanym a LATERAL JOINw niektórych produktach i nowszych wersjach SQL Standard). Jak każda logiczna konstrukcja, nie ma bezpośredniego wpływu na wydajność. Zasadniczo powinniśmy być w stanie napisać zapytanie przy użyciu dowolnej logicznie równoważnej składni, a optymalizator przekształciłby nasze dane wejściowe w dokładnie ten sam fizyczny plan wykonania.

Oczywiście wymagałoby to od optymalizatora znajomości każdej możliwej transformacji i czasu na jej rozważenie. Proces ten może potrwać dłużej niż obecny wiek wszechświata, więc większość produktów komercyjnych nie przyjmuje takiego podejścia. Dlatego składnia zapytań może i często ma wpływ na ostateczną wydajność, choć trudno jest sformułować ogólne stwierdzenia, które z nich są lepsze i dlaczego.

Konkretna forma OUTER APPLY ( SELECT TOP ... )najprawdopodobniej spowoduje połączenie skorelowanych pętli zagnieżdżonych w bieżących wersjach programu SQL Server, ponieważ optymalizator nie zawiera logiki przekształcającej ten wzorzec na równoważny JOIN. Skorelowane łączenie zagnieżdżonych pętli może nie działać dobrze, jeśli wejście zewnętrzne jest duże, a wejście wewnętrzne jest nieindeksowane lub potrzebne strony nie są już w pamięci. Ponadto określone elementy modelu kosztu optymalizatora oznaczają, że skorelowane łączenie zagnieżdżonych pętli jest mniej prawdopodobne niż semantycznie identyczne JOINdo stworzenia równoległego planu wykonania.

Byłem w stanie wykonać to samo zapytanie z pojedynczym złączeniem w lewo i row_number ()

To może, ale nie musi być lepsze w ogólnym przypadku. Będziesz musiał przetestować obie możliwości przy użyciu reprezentatywnych danych. LEFT JOINI ROW_NUMBERna pewno ma potencjał, aby być bardziej wydajny, ale to zależy od dokładnego planu kwerend wybranego kształtu. Podstawowymi czynnikami wpływającymi na efektywność tego podejścia jest dostępność indeksu do pokrycia potrzebnych kolumn i dostarczenia kolejności wymaganej przez klauzule PARTITION BYi ORDER BY. Drugim czynnikiem jest wielkość stołu. Wydajny i dobrze zindeksowany APPLYmoże ROW_NUMBERprzewyższyć optymalne indeksowanie, jeśli zapytanie dotyka relatywnie małej części danej tabeli. Testowanie jest potrzebne.

Paul White mówi GoFundMonica
źródło
2

Pierwsze zapytanie może być uruchamiane równolegle tylko przez jedno żądanie do serwera SQL. Pobrał cały rekord i daje wynik w oparciu o kryteria filtru.

Ale w przypadku drugiego uruchamia wiersz po wierszu i dla każdego wiersza Tabela 2 zostanie zeskanowana i dołączona do wyniku.

jeśli twoje zapytanie zewnętrzne ma mniej rekordu, to drugie jest lepsze (ZEWNĘTRZNE ZASTOSOWANIE). Ale jeśli pierwsze zapytanie może uzyskać więcej danych, powinieneś użyć pierwszego.

użytkownik55424
źródło