Quería saber cuál de los siguientes dos enfoques es más rápido:
1) tres 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) SUMcon FROM-cláusula:
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;
Me sorprendió que la diferencia sea tan grande. La primera consulta con tres subconsultas devuelve el resultado inmediatamente, mientras que el segundo SUMenfoque necesita 18 segundos.
Claimses una vista que selecciona de una tabla que contiene ~ 18 millones de filas. Hay un índice en la columna FK de la ClaimStatustabla que contiene el nombre de estado.
¿Por qué hace una gran diferencia si uso COUNTo SUM?
Planes de ejecución:
Hay 12 estados en total. Esos tres estados pertenecen al 7% de todas las filas.
Esta es la vista real, no estoy seguro si es relevante:
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
fuente
                
                fuente

COUNTversión del plan. ¿Puedes editar el me gusta de laSUMversión para señalar el plan correcto?Authorized.WHERE c.Status = 'Approved' or c.Status = 'Valid' or c.status = 'Reject'a laSUMvariante?Respuestas:
La
COUNT(*)versión puede buscar simplemente el índice que tiene en la columna de estado una vez para cada estado que está seleccionando, mientras que laSUM(...)versión necesita buscar el índice doce veces (el número total de tipos de estado únicos).Claramente, buscar un índice tres veces será más rápido que buscarlo 12 veces.
El primer plan requiere una concesión de memoria de 238 MB, mientras que el segundo plan requiere una concesión de memoria de 650 MB. Es posible que la concesión de memoria más grande no se pueda completar de inmediato, lo que hace que la consulta sea mucho más lenta.
Modifique la segunda consulta para que sea:
Esto permitirá que el optimizador de consultas elimine el 75% de las búsquedas de índice, y debería dar como resultado una concesión de memoria requerida menor, menores requisitos de E / S y un tiempo de resultado más rápido.
La
SUM(CASE WHEN ...)construcción esencialmente evita que el optimizador de consultas empuje losStatuspredicados hacia la parte de búsqueda de índice del plan.fuente
max server memoryopción: debe configurarse con el valor correcto para su sistema. Es posible que desee ver esta pregunta y las respuestas para obtener detalles sobre cómo hacerlo.