sql >> Database >  >> RDS >> Sqlserver

Meest efficiënte manier om rijen te SELECTEREN WAAR DE ID BESTAAT IN een tweede tabel

Samenvatting:

Ik heb elke query elk 10 keer uitgevoerd met behulp van onderstaande testgegevensset..

  1. Een zeer grote subquery-resultatenset (100000 rijen)
  2. Dubbele rijen
  3. Null rijen

Voor alle bovenstaande scenario's geldt dat zowel IN en EXISTS op identieke wijze uitgevoerd.

Wat info over Performance V3-database gebruikt voor het testen. 20000 klanten met 1000000 bestellingen, dus elke klant wordt willekeurig gedupliceerd (in een bereik van 10 tot 100) in de besteltabel.

Uitvoeringskosten, Tijd:
Hieronder ziet u een screenshot van beide lopende query's. Bekijk de relatieve kosten van elke zoekopdracht.

Geheugenkosten:
Geheugentoekenning voor de twee zoekopdrachten is ook hetzelfde..Ik heb MDOP 1 geforceerd om ze niet naar TEMPDB te sturen..

CPU-tijd, leest:

Voor bestaat:

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.

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

In elk geval is de optimizer slim genoeg om de zoekopdrachten te herschikken.

Ik gebruik meestal EXISTS alleen al (mijn mening). Eén use case om EXISTS te gebruiken is wanneer u geen tweede tabelresultatenset wilt retourneren.

Update volgens vragen van Martin Smith:

Ik heb de onderstaande query's uitgevoerd om de meest effectieve manier te vinden om rijen uit de eerste tabel te halen waarvoor in de tweede tabel een verwijzing bestaat.

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)

Alle bovenstaande zoekopdrachten delen dezelfde kosten, met uitzondering van de 2e INNER JOIN , Plan hetzelfde voor de rest.

Geheugentoekenning:
Deze vraag

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

vereiste geheugentoekenning van

Deze vraag

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

vereiste geheugentoekenning van ..

CPU-tijd, leest:
Voor zoekopdracht:

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.

Voor zoekopdracht:

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. SQL:inventariseer geretourneerde rijen binnen elke groep

  2. Hoe MYSQL-database bijwerken met gegevens uit Excel met behulp van ASP.NET?

  3. Wat zijn MySQL-database-engines?

  4. Hoe kan ik alle tabellen in MySQL vinden met specifieke kolomnamen erin?