Tim*_*ter 14 performance sql-server-2005 sql-server t-sql
我想知道以下两种方法中哪一种更快:
1) 三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')
Run Code Online (Sandbox Code Playgroud)
2)SUM
带 -FROM
子句:
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;
Run Code Online (Sandbox Code Playgroud)
我很惊讶差异如此之大。带有三个子查询的第一个查询立即返回结果,而第二种SUM
方法需要 18 秒。
Claims
是从包含约 1800 万行的表中选择的视图。在ClaimStatus
包含状态名称的表的 FK 列上有一个索引。
为什么我使用COUNT
或使用它会产生如此大的差异SUM
?
执行计划:
总共有12种状态。这三个状态属于所有行的 7%。
这是实际视图,我不确定它是否相关:
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
Run Code Online (Sandbox Code Playgroud)
Han*_*non 19
该COUNT(*)
版本能够简单地为您选择的每个状态查找一次您在状态列上的索引,而SUM(...)
版本需要查找索引十二次(唯一状态类型的总数)。
显然,搜索索引 3 次比搜索 12 次要快。
第一个计划需要 238MB 的内存授权,而第二个计划需要 650MB 的内存授权。这可能是更大的内存授权不能立即填补,使得查询慢得多。
将第二个查询更改为:
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
WHERE c.Status = 'Approved'
OR c.Status = 'Valid'
OR c.Status = 'Reject';
Run Code Online (Sandbox Code Playgroud)
这将允许查询优化器消除 75% 的索引查找,并且会导致所需的内存授予、I/O 要求更低,以及更快的结果时间。
该SUM(CASE WHEN ...)
构造本质上可以防止查询优化器将Status
谓词下推到计划的索引查找部分。
归档时间: |
|
查看次数: |
4298 次 |
最近记录: |