SQL łączy Vs SQL Subqueries (wydajność)?

Chciałbym się dowiedzieć czy mam dołączyć zapytanie coś takiego -

Select E.Id,E.Name from Employee E join Dept D on E.DeptId=D.Id

I subquery coś takiego -

Select E.Id,E.Name from Employee Where DeptId in (Select Id from Dept)

Kiedy rozważę wydajność które z dwóch zapytań byłoby szybsze i Dlaczego ?

Czy jest też czas, kiedy powinienem preferować jedno nad drugim?

Przepraszam, jeśli to zbyt trywialne i pytane wcześniej, ale jestem zdezorientowany. Poza tym, byłoby świetnie, jeśli moglibyście mi zasugerować narzędzia powinienem służy do pomiaru wydajności dwóch zapytań. Wielkie dzięki!
Author: Mohammad Dehghan, 2010-10-04

8 answers

Spodziewałbym się, że pierwsze zapytanie będzie szybsze, głównie dlatego, że masz równoważność i wyraźne połączenie. Z mojego doświadczenia {[0] } jest operatorem bardzo wolnym, ponieważ SQL normalnie ocenia go jako serię WHERE klauzul oddzielonych przez " OR " (WHERE x=Y OR x=Z OR...).

Podobnie jak w przypadku wszystkich rzeczy SQL, twój przebieg może się różnić. Prędkość będzie zależeć w dużej mierze od indeksów (czy masz indeksy w obu kolumnach ID? To bardzo pomoże...) między innymi.

Jedyny prawdziwy sposób, aby powiedzieć z 100% pewność, która jest szybsza, to włączyć śledzenie wydajności (statystyki IO są szczególnie przydatne) i uruchomić je oba. Upewnij się, aby wyczyścić pamięć podręczną między uruchomieniami!

 38
Author: JNK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-04 14:44:10

Wydaje mi się, że to pytanie" stare, ale złote". Odpowiedź brzmi: "to zależy!". Spektakle są tak delikatnym tematem, że byłoby zbyt głupio powiedzieć: "nigdy nie używaj subqueries, zawsze Dołącz". W poniższych linkach znajdziesz kilka podstawowych najlepszych praktyk, które uznałem za bardzo pomocne: Tutaj 1 Tutaj 2 Tutaj 3

Mam tabelę z 50000 elementów, wynik, którego szukałem, to 739 elementów.

Moje zapytanie na początku było to:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND p.anno = (
    SELECT MAX(p2.anno) 
    FROM prodotto p2 
    WHERE p2.fixedId = p.fixedId 
)
Wykonanie zajęło 7,9 s.

Moje zapytanie w końcu jest takie:

SELECT  p.id,
    p.fixedId,
    p.azienda_id,
    p.categoria_id,
    p.linea,
    p.tipo,
    p.nome
FROM prodotto p
WHERE p.azienda_id = 2699 AND (p.fixedId, p.anno) IN
(
    SELECT p2.fixedId, MAX(p2.anno)
    FROM prodotto p2
    WHERE p.azienda_id = p2.azienda_id
    GROUP BY p2.fixedId
)

And it taken 0.0256 s

Dobry SQL, dobry.

 23
Author: linuxatico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 03:09:38

Zacznij patrzeć na plany wykonawcze, aby zobaczyć różnice w tym, jak serwer SQl je zinterpretuje. Możesz również użyć profilera do wielokrotnego uruchamiania zapytań i uzyskiwania różnic.

Nie spodziewałbym się, że będą tak strasznie różne, gdzie można uzyskać prawdziwy, duży wzrost wydajności przy użyciu łączy zamiast subqueries jest kiedy używasz skorelowanych subqueries.

EXISTS is czesto better than either of these two and when you are talking left joins where chcesz, aby wszystkie rekordy Nie w lewej tabeli łączenia, to nie istnieje jest często znacznie lepszym wyborem.

 9
Author: HLGEM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-04 15:02:19

Te dwa zapytania mogą nie być semantycznie równoważne. Jeśli pracownik pracuje dla więcej niż jednego działu (możliwe w przedsiębiorstwie, w którym pracuję; co prawda, oznaczałoby to, że Twoja tabela nie jest w pełni znormalizowana), pierwsze zapytanie zwróci zduplikowane wiersze, podczas gdy drugie zapytanie nie. Aby kwerendy były równoważne w tym przypadku, do klauzuli SELECT należy dodać słowo kluczowe DISTINCT, co może mieć wpływ na wydajność.

Uwaga Istnieje zasada projektowania, która Stany tabela powinna modelować podmiot/klasę lub związek między podmiotami / klasami, ale nie oba. Dlatego proponuję stworzyć trzecią tabelę, powiedzmy OrgChart, aby modelować relacje między pracownikami a działami.

 4
Author: onedaywhen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-09 09:51:09

Wydajność zależy od ilości danych, na których wykonujesz...

Jeśli jest mniej danych około 20k. JOIN działa lepiej.

Jeśli dane są bardziej jak 100k+ to w działa lepiej.

Jeśli nie potrzebujesz danych z drugiej tabeli, IN jest dobre, ale jest alwys lepiej przejść do EXISTS.

Wszystkie te kryteria przetestowałem i tabele mają odpowiednie indeksy.

 4
Author: JP Emvia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-12 05:14:50

Wydajność powinna być taka sama; o wiele ważniejsze jest, aby odpowiednie indeksy i klastry były stosowane na Twoich tabelach(istnieją dobre zasoby na ten temat).

(edytowane w celu odzwierciedlenia zaktualizowanego pytania)

 2
Author: Lucero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-04 14:39:34

Wiem, że to stary post, ale myślę, że jest to bardzo ważny temat, szczególnie w dzisiejszych czasach, gdzie mamy rekordy 10M+ i mówimy o terabajtach danych.

Będę również ważyć z następujących obserwacji. Mam około 45m rekordów w tabeli ([dane]), a około 300 rekordów w tabeli [koty]. Mam obszerne indeksowanie dla wszystkich zapytań, o których mam mówić.

Rozważ Przykład 1:

UPDATE d set category = c.categoryname
FROM [data] d
JOIN [cats] c on c.id = d.catid

Kontra Przykład 2:

UPDATE d set category = (SELECT TOP(1) c.categoryname FROM [cats] c where c.id = d.catid)
FROM [data] d

Przykład 1 około 23 min do uruchomienia. Przykład 2 zajął około 5 minut.

Wnioskuję więc, że zapytanie podrzędne w tym przypadku jest znacznie szybsze. Oczywiście należy pamiętać, że używam dysków SSD M. 2 zdolnych do i / O @ 1Gb / s (to bajty, a nie bity), więc moje indeksy są bardzo szybkie. Może to również wpłynąć na prędkość w twojej sytuacji

Jeśli jest to jednorazowe czyszczenie danych, prawdopodobnie najlepiej po prostu zostawić go uruchomić i zakończyć. Używam TOP(10000) i zobaczyć jak długo to trwa i pomnożyć przez liczbę rekordów przed Trafiłem na wielkie pytanie.

Jeśli optymalizujesz produkcyjne bazy danych, zdecydowanie sugerowałbym wstępne przetwarzanie danych, tj. użycie wyzwalaczy lub brokera zadań do aktualizacji rekordów asynchronicznych, aby dostęp w czasie rzeczywistym pobierał statyczne dane.

 1
Author: Arvin Amir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-14 23:35:42

Możesz użyć planu wyjaśnienia, aby uzyskać obiektywną odpowiedź.

Dla Twojego problemu, Filtr Exists prawdopodobnie wykonałby najszybszy.

 0
Author: Snekse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-04 14:44:57