Saya ingin tahu yang mana dari dua pendekatan berikut ini yang lebih cepat:
1) Tiga 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
dengan FROM
-clause:
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;
Saya terkejut bahwa perbedaannya sangat besar. Kueri pertama dengan tiga subkueri mengembalikan hasilnya segera sedangkan SUM
pendekatan kedua membutuhkan 18 detik.
Claims
adalah tampilan yang dipilih dari tabel yang berisi ~ 18 juta baris. Ada indeks pada Kolom FK ke ClaimStatus
tabel yang berisi status-nama.
Mengapa itu membuat perbedaan besar apakah saya menggunakan COUNT
atau SUM
?
Rencana eksekusi:
Ada 12 status secara total. Ketiga status tersebut termasuk dalam 7% dari semua baris.
Ini adalah tampilan yang sebenarnya, saya tidak yakin apakah itu relevan:
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
sumber
sumber
COUNT
versi paket. Bisakah Anda mengedit suka keSUM
versi untuk menunjukkan rencana yang benar?Authorized
.WHERE c.Status = 'Approved' or c.Status = 'Valid' or c.status = 'Reject'
keSUM
varian.Jawaban:
Itu
COUNT(*)
Versi mampu hanya mencari ke dalam indeks yang Anda miliki di kolom status sekali untuk setiap status yang Anda memilih, sedangkanSUM(...)
kebutuhan versi untuk mencari indeks dua belas kali (total jumlah jenis status yang unik).Jelas mencari indeks tiga kali akan lebih cepat daripada mencari itu 12 kali.
Paket pertama membutuhkan hibah memori sebesar 238MB, sedangkan paket kedua membutuhkan hibah memori sebesar 650MB. Ini mungkin bahwa semakin besar hibah memori tidak dapat segera diisi, membuat query yang jauh lebih lambat.
Ubah kueri kedua menjadi:
Ini akan memungkinkan pengoptimal kueri untuk menghilangkan 75% dari indeks yang dicari, dan harus menghasilkan hibah memori yang lebih rendah, persyaratan I / O yang lebih rendah, dan waktu-untuk-hasil yang lebih cepat.
The
SUM(CASE WHEN ...)
konstruk dasarnya mencegah query optimizer dari mendorongStatus
predikat ke dalam indeks mencari bagian dari rencana.sumber
max server memory
opsi - opsi ini harus dikonfigurasikan ke nilai yang benar untuk sistem Anda. Anda mungkin ingin melihat pertanyaan ini dan jawaban untuk perincian tentang bagaimana melakukannya.