sql >> Databáze >  >> RDS >> Sqlserver

Nejúčinnější způsob, jak VYBRAT řádky, KDE EXISTUJE ID VE druhé tabulce

Shrnutí:

Každý dotaz jsem spustil 10krát pomocí níže uvedené testovací sady dat..

  1. Velmi velká sada výsledků poddotazu (100 000 řádků)
  2. Duplicitní řádky
  3. Nové řádky

Pro všechny výše uvedené scénáře jsou oba IN a EXISTS provedeny stejným způsobem.

Některé informace o databázi Performance V3 používá se pro testování. 20 000 zákazníků, kteří mají 1 000 000 objednávek, takže každý zákazník je náhodně duplikován (v rozsahu 10 až 100) v tabulce objednávek.

Náklady na provedení, čas:
Níže je snímek obrazovky obou spuštěných dotazů. Sledujte relativní cenu každého dotazu.

Cena paměti:
Přidělení paměti pro dva dotazy je také stejné..Vynutil jsem MDOP 1, abych je nepřesypal do TEMPDB..

Čas CPU, čtení:

Pro existuje:

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.

Pro 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.

V každém případě je optimalizátor dostatečně chytrý, aby přeuspořádal dotazy.

Mám tendenci používat EXISTS jen když (můj názor). Jeden případ použití pro použití EXISTS je, když nechcete vrátit druhou sadu výsledků tabulky.

Aktualizace podle dotazů od Martina Smithe:

Spustil jsem níže uvedené dotazy, abych našel nejúčinnější způsob, jak získat řádky z první tabulky, pro kterou existuje odkaz ve druhé tabulce.

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)

Všechny výše uvedené dotazy sdílejí stejnou cenu s výjimkou 2. INNER JOIN , Plán je stejný pro zbytek.

Přidělení paměti:
Tento dotaz

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

požadované přidělení paměti ve výši

Tento dotaz

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

požadované přidělení paměti ..

Čas CPU, čtení:
Pro dotaz:

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.

Pro dotaz:

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. ORACLE (11.2.0.1.0) - Rekurzivní CTE s výrazem data

  2. 'LIKE ('%this%' OR '%that%') a něco=jiné nefunguje

  3. Jak mohu dešifrovat hash hesla v PHP?

  4. Java PreparedStatement si stěžuje na syntaxi SQL při provádění()