Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Najbardziej efektywny sposób na WYBIERANIE wierszy GDZIE ID ISTNIEJE W drugiej tabeli

Podsumowanie:

Każde zapytanie wykonałem 10 razy, używając poniższego zestawu danych testowych.

  1. Bardzo duży zestaw wyników podzapytania (100000 wierszy)
  2. Zduplikowane wiersze
  3. Zerowe wiersze

We wszystkich powyższych scenariuszach zarówno IN i EXISTS wykonywane w identyczny sposób.

Kilka informacji o bazy danych Performance V3 używane do testowania.20000 klientów posiadających 1000000 zamówień, więc każdy klient jest losowo duplikowany (w zakresie od 10 do 100) w tabeli zamówień.

Koszt wykonania,Czas:
Poniżej znajduje się zrzut ekranu obu uruchomionych zapytań. Obserwuj względny koszt każdego zapytania.

Koszt pamięci:
Przydział pamięci dla dwóch zapytań jest również taki sam... Wymusiłem MDOP 1, aby nie rozlać ich do TEMPDB..

Czas procesora, odczyty:

W przypadku istnienia:

Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 109, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 1, logical reads 3855, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 469 ms,  elapsed time = 595 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

Dla IN:

(20000 row(s) affected)
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 1, logical reads 109, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 1, logical reads 3855, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 547 ms,  elapsed time = 669 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

W każdym przypadku optymalizator jest wystarczająco inteligentny, aby zmienić kolejność zapytań.

Zwykle używam EXISTS tylko chociaż (moja opinia). Jeden przypadek użycia do użycia EXISTS jest wtedy, gdy nie chcesz zwracać zestawu wyników drugiej tabeli.

Aktualizuj zgodnie z zapytaniami Martina Smitha:

Uruchomiłem poniższe zapytania, aby znaleźć najbardziej efektywny sposób na pobranie wierszy z pierwszej tabeli, do której odwołanie istnieje w drugiej tabeli.

SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid   

SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid

SELECT *
FROM Customers C
WHERE EXISTS(SELECT 1 FROM Orders o WHERE o.custid = c.custid)

SELECT *
FROM Customers c
WHERE custid IN (SELECT custid FROM Orders)

Wszystkie powyższe zapytania mają ten sam koszt, z wyjątkiem drugiego INNER JOIN , Plan jest taki sam dla reszty.

Przyznanie pamięci:
To zapytanie

SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid 

wymagane przyznanie pamięci

To zapytanie

SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid 

wymagane przyznanie pamięci ..

Czas procesora, odczyty:
W przypadku zapytania:

SELECT DISTINCT c.*
FROM Customers c
JOIN Orders o ON o.custid = c.custid   

(20000 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 48, logical reads 1344, physical reads 96, read-ahead reads 1248, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 5, logical reads 3929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Customers'. Scan count 5, logical reads 322, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 1453 ms,  elapsed time = 781 ms.

Dla zapytania:

SELECT c.*
FROM Customers c
INNER JOIN (SELECT DISTINCT custid FROM Orders) AS o ON o.custid = c.custid

(20000 row(s) affected)
Table 'Customers'. Scan count 5, logical reads 322, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Orders'. Scan count 5, logical reads 3929, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 1499 ms,  elapsed time = 403 ms.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dostosuj alarmy Spotlight Cloud

  2. Alternatywa do używania WHERE ... IN (...) do powolnych zapytań SQL

  3. Dzielenie łańcucha na dwie części i wybieranie na dwie zmienne

  4. Przekaż identyfikator najemcy przez połączenie z serwerem sql

  5. SQL . SP lub funkcja powinna obliczyć następną datę na piątek