2011-01-28 19 views
5

¿Puede alguien ayudarme a sintonizar esta consulta SQL?¿Por qué este SQL da como resultado Index Scan en lugar de Index Search?

SELECT a.BuildingID, a.ApplicantID, a.ACH, a.Address, a.Age, a.AgentID, a.AmenityFee, a.ApartmentID, a.Applied, a.AptStatus, a.BikeLocation, a.BikeRent, a.Children, 
     a.CurrentResidence, a.Email, a.Employer, a.FamilyStatus, a.HCMembers, a.HCPayment, a.Income, a.Industry, a.Name, a.OccupancyTimeframe, a.OnSiteID, 
     a.Other, a.ParkingFee, a.Pets, a.PetFee, a.Phone, a.Source, a.StorageLocation, a.StorageRent, a.TenantSigned, a.WasherDryer, a.WasherRent, a.WorkLocation, 
     a.WorkPhone, a.CreationDate, a.CreatedBy, a.LastUpdated, a.UpdatedBy 
FROM dbo.NPapplicants AS a INNER JOIN 
     dbo.NPapartments AS apt ON a.BuildingID = apt.BuildingID AND a.ApartmentID = apt.ApartmentID 
WHERE (apt.Offline = 0) 
AND  (apt.MA = 'M') 

.

Aquí es lo que el plan de ejecución se parece a:

.

enter image description here

Lo que no entiendo es por qué estoy recibiendo un recorrido de índice de NPapplicants. Tengo un índice que cubre BuildingID y ApartmentID. ¿No debería ser eso usado?

+0

¿Cuántas filas hay en la tabla NPapplicants? –

+0

La imagen muestra 7775, de la última actualización de estadísticas – RichardTheKiwi

Respuesta

6

Es porque está esperando cerca de 10K registros para regresar de las coincidencias. Volver a los datos para recuperar otras columnas con las teclas 10K es equivalente a algo así como el rendimiento de solo escanear 100K registros (como mínimo) y el filtrado utilizando la coincidencia hash.

En cuanto al acceso a la otra tabla, Query Optimizer ha decidido que su índice es útil (probablemente contra Offline o MA) por lo que busca en ese índice obtener las claves de combinación.

Estos dos son HASH combinados para intersecciones para producir la salida final.

+0

Gracias por la respuesta. Entonces estás diciendo que no hay mucho que pueda hacer. La consulta es tan precisa como se va a obtener con tantos datos para regresar? – Axeva

+0

Para esa cantidad de columnas de la tabla del solicitante, sí, eso es lo mejor posible. A menos que el filtro en 'apartments (Offline, MA)' sea realmente realmente selectivo (como 1% o menos) y 'count (apartments) RichardTheKiwi

3

Buscar en un índice B-Tree es varias veces más caro que un examen de tabla (por registro).

Además, se debe realizar otra búsqueda en el índice agrupado para recuperar los valores de otras columnas.

Si se espera que una gran parte de los registros coincidan, es más económico escanear el índice agrupado.

Para asegurarse de que el optimizador había elegido el mejor método, es posible ejecutar este:

SET STATISTICS IO ON 
SET STATSTICS TIME ON 

SELECT a.BuildingID, a.ApplicantID, a.ACH, a.Address, a.Age, a.AgentID, a.AmenityFee, a.ApartmentID, a.Applied, a.AptStatus, a.BikeLocation, a.BikeRent, a.Children, 
     a.CurrentResidence, a.Email, a.Employer, a.FamilyStatus, a.HCMembers, a.HCPayment, a.Income, a.Industry, a.Name, a.OccupancyTimeframe, a.OnSiteID, 
     a.Other, a.ParkingFee, a.Pets, a.PetFee, a.Phone, a.Source, a.StorageLocation, a.StorageRent, a.TenantSigned, a.WasherDryer, a.WasherRent, a.WorkLocation, 
     a.WorkPhone, a.CreationDate, a.CreatedBy, a.LastUpdated, a.UpdatedBy 
FROM dbo.NPapplicants AS a INNER JOIN 
     dbo.NPapartments AS apt ON a.BuildingID = apt.BuildingID AND a.ApartmentID = apt.ApartmentID 
WHERE (apt.Offline = 0) 
AND  (apt.MA = 'M') 

SELECT a.BuildingID, a.ApplicantID, a.ACH, a.Address, a.Age, a.AgentID, a.AmenityFee, a.ApartmentID, a.Applied, a.AptStatus, a.BikeLocation, a.BikeRent, a.Children, 
     a.CurrentResidence, a.Email, a.Employer, a.FamilyStatus, a.HCMembers, a.HCPayment, a.Income, a.Industry, a.Name, a.OccupancyTimeframe, a.OnSiteID, 
     a.Other, a.ParkingFee, a.Pets, a.PetFee, a.Phone, a.Source, a.StorageLocation, a.StorageRent, a.TenantSigned, a.WasherDryer, a.WasherRent, a.WorkLocation, 
     a.WorkPhone, a.CreationDate, a.CreatedBy, a.LastUpdated, a.UpdatedBy 
FROM dbo.NPapplicants WITH (INDEX (index_name)) AS a 
INNER JOIN 
     dbo.NPapartments AS apt ON a.BuildingID = apt.BuildingID AND a.ApartmentID = apt.ApartmentID 
WHERE (apt.Offline = 0) 
AND  (apt.MA = 'M') 

Reemplazar index_name con el nombre real de su índice y comparar los tiempos de ejecución y el número de I/O operaciones (como se visto en la pestaña de mensajes)

+1

Interesante. Sin el índice: tiempo de CPU = 93 ms, tiempo transcurrido = 679 ms. /// Con el índice: tiempo de CPU = 172 ms, tiempo transcurrido = 666 ms. – Axeva

+0

@Axeva: como se puede ver, el optimizador de mama no hizo ningún tonto. En campos no selectivos, una búsqueda de índice es más costosa, especialmente con un índice que no cubre. – Quassnoi