Następujące zapytania SQL są takie same:
SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;
SELECT column1, column2
FROM table1 JOIN table2
ON table1.id = table2.id;
I z pewnością skutkują tymi samymi planami zapytań na każdym DBMS, którego kiedykolwiek próbowałem.
Ale co jakiś czas czytam lub słyszę opinię, że jedna jest zdecydowanie lepsza od drugiej. Oczywiście twierdzenia te nigdy nie są uzasadnione wyjaśnieniem.
Tam, gdzie pracuję, wydaje się, że druga wersja jest faworyzowana przez większość deweloperów, dlatego też dążę do tego stylu, aby zminimalizować zaskoczenie. Ale w moim sercu naprawdę myślę o tym pierwszym (ponieważ tak właśnie się nauczyłem).
Czy jedna z tych form jest obiektywnie lepsza od drugiej? Jeśli nie, jakie byłyby powody używania jednego nad drugim?
sql
coding-style
SingleNegationElimination
źródło
źródło
Odpowiedzi:
Uważam, że druga forma jest lepsza. Może dlatego, że tak się nauczyłem, przyznaję, ale mam jeden konkretny powód - rozdzielenie obaw. Umieszczenie pól używanych do łączenia tabel w klauzuli where może prowadzić do trudności w zrozumieniu zapytań.
Na przykład weź następujące zapytanie:
Powyższe zapytanie zawiera warunki łączenia tabel i rzeczywiste warunki logiki biznesowej połączone w jedną przestrzeń. Przy dużym zapytaniu może to być bardzo trudne do zrozumienia.
Jednak teraz weź ten kod:
W takim przypadku wszystko, co ma związek z tabelami lub ich relacją, jest odizolowane od klauzuli from, podczas gdy rzeczywista logika biznesowa dla ograniczenia zapytań znajduje się w klauzuli where. Myślę, że jest to o wiele bardziej zrozumiałe, szczególnie w przypadku większych zapytań.
źródło
Składnia złączenia zastąpiła starą składnię przecinków w 1992 r. Obecnie nie ma powodu, aby pisać kod ze składnią przecinków. Nic nie zyskujesz i masz problemy, których po prostu nie masz z jawną składnią.
Po pierwsze, gdy dostajesz bardziej skomplikowane zapytania, bardzo łatwo jest wykonać przypadkowe połączenie krzyżowe, pomijając warunek where. Jest to coś, co jawna składnia łączenia może zapobiec, ponieważ wystąpi błąd składniowy.
Jeśli zamierzasz połączyć krzyżowo, jawna składnia sprzężenia wyjaśni to, gdy w domniemanej składni ktoś przeprowadzający konserwację może założyć, że zapomniałeś dodać klauzuli where.
Następnie pojawia się problem lewych i prawych złączeń, które są problematyczne przynajmniej w niektórych dbach przy użyciu niejawnej składni. Są one przestarzałe w SQL Server i w rzeczywistości nie zwracają poprawnych wyników nawet w starszych wersjach. Żadne zapytanie wymagające połączenia zewnętrznego nie powinno zawierać niejawnej składni w programie SQL Server.
Ponadto widziałem pytania tutaj i na innych stronach, na których zdarzały się złe wyniki, gdy ludzie mieszali niejawne i jawne sprzężenia (na przykład dodając lewe sprzężenie), więc źle jest mieszać je.
Wreszcie wiele osób korzystających z niejawnych połączeń nie rozumie połączeń. Jest to krytyczne zrozumienie, że musisz efektywnie przeszukiwać bazę danych.
źródło
Ha. Zdarzyło mi się znaleźć możliwą odpowiedź na własne pytanie, przeglądając dokumentację PostgreSQL . Podsumowując, co wyjaśnia ta strona, wynikowe zapytanie jest nadal takie samo, ale liczba planów, które optymalizator musi rozważyć, rośnie wykładniczo wraz z liczbą sprzężeń.
Po około sześciu takich połączeniach liczba jest tak duża, że czas na zaplanowanie zapytania może być zauważalny, a po około dziesięciu optymalizator przełączy się z wyczerpującego wyszukiwania planów na wyszukiwanie probabilistyczne i może nie uzyskać optymalnego planu .
Ustawiając parametr czasu wykonywania, możesz poinstruować planistę, aby traktował wyraźnie wymienione połączenia wewnętrzne i krzyżowe inaczej niż sprzężenia niejawne, zmuszając je do początku planu i nie analizując innych opcji.
Warto zauważyć, że domyślne zachowanie jest takie samo w obu przypadkach, a uzyskanie alternatywnych planów wymaga znajomości elementów wewnętrznych dbms i osobliwości danych tabel, aby uzyskać inny wynik
źródło
Oto widok teorii zbiorów:
Kiedy używasz przecinka, aby oddzielić dwie (lub więcej) nazwy tabeli, to zamierzasz uzyskać produkt kartezjański. Każdy wiersz „lewego” stołu będzie „dopasowany” (konkatenowany) z rzędem prawego stołu.
Teraz, jeśli napiszesz coś w klauzuli where, będzie to jak nałożenie warunku na tę „konkatenację”, mówiącą, które wiersze „połączyć” z którymi wierszami.
W rzeczywistości jest to „łączenie” wierszy :), a zatem słowo kluczowe join, które pomaga zapewnić bardziej czytelną składnię i jest bardziej zrozumiałe, że „naprawdę” chcesz dołączyć do niektórych wspólnych wartości. Podobne do tego, co @Dustin wyjaśnił powyżej.
Teraz każdy DBMS jest inteligentny, tzn. Nie oblicza najpierw produktu kartezjańskiego, a następnie odfiltrowuje dane (wyjątkowo marnotrawstwo), a raczej robi to na podstawie struktury zapytania. Jedyną rzeczą, o której mogę myśleć, jest to, że kiedy poprosisz o „dołączenie”, to tak, jakby wyraźne było łączenie działania i prawdopodobnie pomaga szybciej uruchomić kod (o ile? Musisz go profilować i zobaczyć), ale w Przypadek oddzielony przecinkami potrzebuje trochę czasu, aby „wymyślić” optymalną strategię. Mogę się mylić, ale zgaduję, jak można to kodować ...
źródło
Myślę, że ogólnie lepiej jest użyć instrukcji JOIN w tej sprawie.
Jeśli w przyszłości pojawi się sytuacja, która wymaga zmiany instrukcji z WEJŚCIA WEWNĘTRZNEGO na WEJŚCIE ZEWNĘTRZNE, będzie to znacznie łatwiejsze w przypadku drugiej instrukcji.
źródło
Każdy RDBMS sprawi, że będą one tym samym pod względem wykonania. Wszystko sprowadza się do tego, czy ktoś jest bardziej czytelny i wyrazisty.
Użyj DOŁĄCZ, aby było jasne, co to jest łączenie złączeń, a jaki jest faktyczny wybór, jak w:
vs.
Ten drugi przypadek natychmiast wyjaśnia, który jest warunkiem łączenia, a który jest kryterium wyboru.
źródło
Tylko raz widziałem te dwa wyniki w innym zestawie optymalizacji i jeśli pamięć służy, to było w ms-sql2k na naprawdę włochatym zapytaniu. W tym jednym przykładzie stara forma użyta z * = spowodowała około 4x szybszą wydajność. Nikt, w tym nasi technicy Microsoft, nie potrafiłby nigdy wyjaśnić dlaczego. Faceci ze stwardnienia rozsianego opisali to jako błąd. Nigdy więcej tego nie widziałem.
Ponieważ większość RDBMS jest wystarczająco inteligentna, aby nie robić pełnych kartezjanów, największym powodem, dla którego mogę myśleć o nieużywaniu go (poza tym, że jest to amortyzowane) jest to, że większość osób poniżej 30-35 lat, z którymi pracowałem, nigdy nie widziała stara forma wcześniej i strasznie się zagubiła, gdy ją napotka.
źródło
Stary styl jest przestarzały, nie należy go używać.
Nie powinno być nawet sporu o to, czy ktoś jest lepszy, czy nie. Nowy kod nie powinien używać starej składni.
źródło
Jednym z powodów, dla których składnia jest bardziej zwięzła, jest to, że jest ona bardziej zwięzła, więc jeśli czujesz się komfortowo, łatwiej ją odczytać. Myślę, że pełny opis przypadku jest podobny do wypisywania arytmetyki w języku COBOL, np. MULTIPLY A BY B DAJĄC C.
źródło