简体   繁体   English

为什么这个SQL导致索引扫描而不是索引搜索?

[英]Why does this SQL result in Index Scan instead of an Index Seek?

Can someone please help me tune this SQL query? 有人可以帮我调整这个SQL查询吗?

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')

.

Here's what the Execution Plan looks like: 以下是执行计划的样子:

.

在此输入图像描述

What I don't understand is why I'm getting a Index Scan for NPapplicants. 我不明白的是为什么我要为NPapplicants进行索引扫描。 I have an Index that covers BuildingID and ApartmentID. 我有一个涵盖BuildingID和ApartmentID的索引。 Shouldn't that be used? 不应该使用吗?

It is because it is expecting close to 10K records to return from the matches. 这是因为期待从比赛中返回接近10K的记录。 To go back to the data to retrieve other columns using 10K keys is equivalent to something like the performance of just scanning 100K records (at the very least) and filtering using hash match. 回到数据以使用10K密钥检索其他列相当于仅扫描100K记录(至少)和使用哈希匹配过滤的性能。

As for access to the other table, the Query Optimizer has decided that your index is useful (probably against Offline or MA ) so it is seeking on that index to get the join keys. 至于对其他表的访问,查询优化器已经确定您的索引是有用的(可能是针对OfflineMA ),因此它正在寻找该索引以获取连接键。

These two are then HASH matched for intersections to produce the final output. 然后将这两个HASH匹配用于交叉点以产生最终输出。

A seek in a B-Tree index is several times as expensive as a table scan (per record). B-Tree索引中的搜索是表扫描(每个记录)的几倍。

Additionally, another seek in the clustered index should be made to retrieve the values of other columns. 此外,应该在聚集索引中进行另一次搜索以检索其他列的值。

If a large portion of records is expected to match, then it is cheaper to scan the clustered index. 如果预计大部分记录匹配,则扫描聚簇索引会更便宜。

To make sure that the optimizer had chosen the best method, you may run this: 要确保优化器选择了最佳方法,您可以运行以下命令:

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')

Replace index_name with the actual name of your index and compare the execution times and the numbers of I/O operations (as seen in the messages tab) index_name替换为索引的实际名称,并比较执行时间和I/O操作数(如消息选项卡中所示)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM