Ich wollte wissen, welcher der beiden folgenden Ansätze schneller ist:
1) Drei COUNT
:
SELECT Approved = (SELECT COUNT(*) FROM dbo.Claims d
WHERE d.Status = 'Approved'),
Valid = (SELECT COUNT(*) FROM dbo.Claims d
WHERE d.Status = 'Valid'),
Reject = (SELECT COUNT(*) FROM dbo.Claims d
WHERE d.Status = 'Reject')
2) SUM
mit FROM
-Klausel:
SELECT Approved = SUM(CASE WHEN Status = 'Approved' THEN 1 ELSE 0 END),
Valid = SUM(CASE WHEN Status = 'Valid' THEN 1 ELSE 0 END),
Reject = SUM(CASE WHEN Status = 'Reject' THEN 1 ELSE 0 END)
FROM dbo.Claims c;
Ich war überrascht, dass der Unterschied so groß ist. Die erste Abfrage mit drei Unterabfragen gibt das Ergebnis sofort zurück, während die zweite Abfrage SUM
18 Sekunden benötigt.
Claims
ist eine Ansicht, die aus einer Tabelle mit ~ 18 Millionen Zeilen auswählt. In der FK-Spalte befindet sich ein Index zu der ClaimStatus
Tabelle, die den Statusnamen enthält.
Warum macht es so einen großen Unterschied, ob ich benutze COUNT
oder SUM
?
Ausführungspläne:
Insgesamt gibt es 12 Status. Diese drei Status gehören zu 7% aller Zeilen.
Dies ist die aktuelle Ansicht, ich bin nicht sicher, ob es relevant ist:
CREATE VIEW [dbo].[Claims]
AS
SELECT
mu.Marketunitname AS MarketUnit,
c.Countryname AS Country,
gsp.Gspname AS GSP,
gsp.Wcmskeynumber AS GspNumber,
sl.Slname AS SL,
sl.Wcmskeynumber AS SlNumber,
m.Modelname AS Model,
m.Salesname AS [Model-Salesname],
s.Claimstatusname AS [Status],
d.Work_order AS [Work Order],
d.Ssn_number AS IMEI,
d.Ssn_out,
Remarks,
d.Claimnumber AS [Claim-Number],
d.Rma_number AS [RMA-Number],
dbo.ToShortDateString(d.Received_Date, 1) AS [Received Date],
Iddata,
Fisl,
Fimodel,
Ficlaimstatus
FROM Tabdata AS d
INNER JOIN Locsl AS sl
ON d.Fisl = sl.Idsl
INNER JOIN Locgsp AS gsp
ON sl.Figsp = gsp.Idgsp
INNER JOIN Loccountry AS c
ON gsp.Ficountry = c.Idcountry
INNER JOIN Locmarketunit AS mu
ON c.Fimarketunit = mu.Idmarketunit
INNER JOIN Modmodel AS m
ON d.Fimodel = m.Idmodel
INNER JOIN Dimclaimstatus AS s
ON d.Ficlaimstatus = s.Idclaimstatus
INNER JOIN Tdefproducttype
ON d.Fiproducttype = Tdefproducttype.Idproducttype
LEFT OUTER JOIN Tdefservicelevel
ON d.Fimaxservicelevel = Tdefservicelevel.Idservicelevel
LEFT OUTER JOIN Tdefactioncode AS ac
ON d.Fimaxactioncode = ac.Idactioncode
sql-server
performance
sql-server-2005
t-sql
Tim Schmelter
quelle
quelle
COUNT
Version des Plans verweisen . Können Sie sich dergleichen auf die bearbeitenSUM
Version auf den richtigen Plan zu zeigen?Authorized
.WHERE c.Status = 'Approved' or c.Status = 'Valid' or c.status = 'Reject'
auf dieSUM
Variante.Antworten:
Die
COUNT(*)
Version kann den Index, den Sie in der Statusspalte haben, einfach einmal für jeden ausgewählten Status durchsuchen, während dieSUM(...)
Version den Index zwölfmal durchsuchen muss (die Gesamtzahl der eindeutigen Statustypen).Die dreimalige Suche nach einem Index ist eindeutig schneller als die zwölfmalige Suche.
Der erste Plan erfordert eine Speicherzuweisung von 238 MB, während der zweite Plan eine Speicherzuweisung von 650 MB erfordert. Es kann sein , dass die größere Speichergewährungs nicht sofort gefüllt werden kann, so dass die Abfrage , die viel langsamer.
Ändern Sie die zweite Abfrage in:
Auf diese Weise kann das Abfrageoptimierungsprogramm 75% der Indexsuchen eliminieren und sollte sowohl zu einer geringeren erforderlichen Speicherzuweisung als auch zu geringeren E / A-Anforderungen und einer schnelleren Zeit bis zum Ergebnis führen.
Das
SUM(CASE WHEN ...)
Konstrukt verhindert im Wesentlichen, dass der Abfrageoptimierer dieStatus
Prädikate in den Indexsuchabschnitt des Plans drückt .quelle
max server memory
Option prüfen - sie sollte auf den richtigen Wert für Ihr System konfiguriert sein. Sie können sich diese Frage und die Antworten ansehen, um Einzelheiten dazu zu erfahren.