UŻYWANIE konstruktu w klauzuli JOIN może w niektórych przypadkach wprowadzić bariery optymalizacyjne?

35

Zwrócono mi uwagę, że USINGkonstrukcja (zamiast ON) w FROMklauzuli SELECTzapytań może w niektórych przypadkach wprowadzić bariery optymalizacyjne.

Mam na myśli to słowo kluczowe:

WYBIERZ *
Od
Dołącz b UŻYCIEM (a_id)

Tylko w bardziej skomplikowanych przypadkach.

Kontekst: ten komentarz do tego pytania .

Używam tego bardzo często i jak dotąd niczego nie zauważyłem. Byłbym bardzo zainteresowany przypadkiem testowym pokazującym efekt lub jakiekolwiek linki do dalszych informacji. Moje poszukiwania były puste.

Idealną odpowiedzią byłby przypadek testowy, który wykazywałby USING (a_id)gorszą wydajność w porównaniu z alternatywną klauzulą ​​łączenia ON a.a_id = b.a_id- jeśli tak się może zdarzyć.

Erwin Brandstetter
źródło
2
@kgrittn: Tego się ogólnie spodziewałem: USINGjest to nieco szybsze - ponieważ powoduje to o jedną kolumnę mniej w macierzy wyników. Twoje ustalenia pochodzą z 2005 i 2008 roku. Zakładam, że wszelkie problemy zostały już naprawione. Jednakże , można zobaczyć możliwe ograniczenie: łączy się USINGmogą być zastosowane w celu , jak otrzymanego kolumny łączącej jest wspólnym produktem. Potencjalnie ogranicza to opcje ponownego zamawiania JOIN.
Erwin Brandstetter,
1
Znalazłem ten wątek, który mógł mieć coś wspólnego ze zniechęcaniem mnie do używania go tak często, jak miałem, ponieważ WIDOK z warunkiem UŻYTKOWANIA na złączeniu może powodować problemy podczas zrzutu / przywracania: archives.postgresql.org/pgsql- bugs / 2011-06 / msg00030.php Nadal mam dokuczliwe wrażenie, że był inny wątek związany z problemami z wydajnością przy UŻYWANIU, w którym obejście miało być WŁĄCZONE, ale myślę, że zrezygnuję z jego znalezienia. Prawdopodobnie bezpiecznie jest używać go poza widokami i pamiętaj, aby wypróbować ON jako krok diagnostyczny, jeśli zapytanie jest wolne.
kgrittn
1
Wygląda na to, że „używanie” czyni kod trochę czytelnym, ale wydaje mi się, że oba pola wymagają tej samej nazwy. Nie sądzę, że używanie będzie miało lepszą wydajność niż „on”, ponieważ DB i tak musi dopasować, to tak, jakby wybrane miały taką samą wydajność niż łączenie (popraw mnie, jeśli się mylę), różnica polega na tym, że Join jest czystszy i łatwiejszy w utrzymaniu.
jcho360
2
@HLGEM: To tylko symboliczna nazwa, a przy dwóch tabelach, jak w moim przykładzie, nie ma miejsca na zamieszanie. Mimo to poprawiłem pytanie. Nie chciałbym zachęcać do niefortunnego użycia idjako nazwy kolumny.
Erwin Brandstetter
2
@ChristiaanWesterbeek: Nie zgadzam się. „Go-to place” dla pogłębionej odpowiedzi Postgres to (nadal) mailing. Tylko nieliczni deweloperzy Postgres są aktywni na SO, ale wszyscy deweloperzy Postgres i eksperci czytają listę mailingową
a_horse_w_na_nazwa

Odpowiedzi:

12

Erwin: Zgodziłbym się z tezą, że WYKORZYSTANIE powodowania sztywnego zamawiania mogłoby stworzyć wiele skrajnych przypadków, w których wykluczone byłyby optymalne plany. Niedawno pomogłem komuś, kto miał coś takiego w swoim zapytaniu:

LEFT JOIN ( 
     a 
     JOIN b ON a.id = b.a_id
     JOIN c ON b.c_id = c.id
) ON a.id = something.a_id
LEFT JOIN (
     table1 t1
     JOIN table2 t2 ON t1.some_field = t2.other_field
     JOIN talbe3 t3 ON t2.yafield = t3.something_else
) ON ....
repeat a few more times

W jego przypadku najgorszym z tych bloków łączenia było wywołanie zagnieżdżonej pętli łączącej około 200 000 wierszy, około 20 000 razy (wykonaj obliczenia matematyczne), a ponieważ kluczy nie można było wypchnąć do indeksów, było to skanowanie sekwencyjne. Oznaczało to, że ogólne zapytanie zajęło około 3 godzin z powodu zmian w planie kaskadowym. Rozdzielając lewe złączenie, klawisze można było przesunąć w dół, a zapytanie uruchomiono w ciągu kilku sekund. Oczywiście nie jest to dokładnie równoważne, dlatego planista nie może traktować ich jako równoważnych, dlatego pozostawiono wymyślenie tego planu jako sprzężenia mieszającego, a następnie wykonanie zagnieżdżonej pętli, która była boleśnie powolna.

Za każdym razem, gdy sztywno wymuszasz przejście sprzężeń w określonej kolejności, wprowadzasz przypadki, w których informacje o filtrze klucza mogą nie być jeszcze dostępne w trakcie wykonywania planu, a więc co można zrobić później w przypadku szybkiego skanowania indeksu / łączenia mieszającego może być konieczne wykonanie znacznie wolniej podczas skanowania w pętli zagnieżdżonej / sekwencyjnej, więc chociaż powyższy fragment nie jest natychmiast równoważny, pokazuje ten sam problem.

Chris Travers
źródło