SQL Server多关联查询优化咨询:缺失索引是否应创建?
问题背景
近期SQL Server已升级至2019版本,因不常执行该查询,无法确认迁移前速度是否更快。当前该多关联查询在SSMS中执行需45秒以上,Web环境触发SQL超时错误。所有表均通过各自主键关联至tblGivingContacts表(例如tblStudents.studentID、tblGivingCampaigns.campaignID等)。
查询语句
SELECT DISTINCT tblGivingContacts.[ID], tblGivingContacts.[contactID], tblGivingContacts.[contactType], tblGivingContacts.[contactTypeSub], tblGivingContacts.[lastUpdated], tblGivingContacts.[DonationCurrency], tblGivingContacts.[DonationAmount], tblGivingContacts.[Notes], tblGivingContacts.[ProcessedBy], tblGivingContacts.[scheduleID], firstname, lastname, fathersname, mothersname, email, fathersemail, mothersemail, DonationStatusName, callStatusName, CampaignName, phone1, phone2, cellphone, FathersCellphone, MothersCellphone, tblStudents.Country AS StudentCountry, tblAlumni.Country AS AlumniCountry, MothersCountry, FathersCountry, (SELECT TOP 1 SchoolYear FROM tblStudentStudyYears WHERE tblStudentStudyYears.studentID = tblStudents.studentID ORDER BY schoolYear DESC) AS SchoolYear FROM [tblGivingContacts] INNER JOIN tblStudents ON tblGivingContacts.contactID = tblStudents.studentID INNER JOIN tblParents ON tblParents.studentID = tblStudents.studentID INNER JOIN tblGivingCampaigns ON tblGivingContacts.campaignID = tblGivingCampaigns.campaignID LEFT OUTER JOIN tblAlumni ON tblAlumni.studentID = tblStudents.studentID LEFT OUTER JOIN tblGivingCallStatus ON tblGivingContacts.callStatusID = tblGivingCallStatus.callStatusID LEFT OUTER JOIN tblGivingDonationStatus ON tblGivingContacts.donationStatusID = tblGivingDonationStatus.donationStatusID
执行分析信息
查看执行计划后发现:tblGivingContacts.*占38%成本,tblParents列占27%成本。执行计划给出的缺失索引建议如下:
Missing Index Details from SQLQuery1.sql The Query Processor estimates that implementing the following index could improve the query cost by 28.7418%. */ /* USE [database] GO CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] ON [dbo].[tblParents] ([studentID]) INCLUDE ([FathersName],[FathersCountry],[FathersEmail],[FathersCellphone],[MothersName],[MothersCountry],[MothersEmail],[MothersCellphone])
咨询问题
- 该索引是否建议创建?
- 创建后有何弊端?
- 若后续修改查询或新增SELECT列会有什么影响?
问题解答
1. 是否建议创建该索引?
建议创建。从执行计划来看,tblParents的查询成本占比27%,这个索引是针对性的覆盖索引:通过关联字段studentID快速定位数据,同时把当前查询需要的所有tblParents字段都包含在索引中,避免了回表查找主键索引的额外开销。执行计划估算能降低28%左右的查询成本,对当前超时的查询优化效果会很明显,大概率能将执行时间压缩到可接受范围,解决Web端的超时问题。
2. 创建后的弊端
- 写入性能损耗:对
tblParents执行插入、更新、删除操作时,除了维护主键索引,还要同步维护这个非聚集索引,会增加少量写入开销。如果tblParents是高频写入表,这个影响会更显著;若日常写入量小,基本可忽略。 - 额外存储空间占用:该索引包含8个字段,会占用额外的磁盘空间。但相比于解决查询超时的收益,只要磁盘空间充足,这点代价完全值得。
- 索引维护成本增加:如果数据库有定期索引重建/重组的作业,这个索引会延长维护作业的时间、消耗更多资源,不过只要不是索引数量过多,影响有限。
3. 后续修改查询或新增SELECT列的影响
- 新增
tblParents字段不在INCLUDE列表中:当查询需要tblParents的其他字段时,这个覆盖索引会失效,SQL Server被迫回表查找主键索引,查询性能会回落,甚至回到之前的慢状态。此时需要更新索引,将新增字段加入INCLUDE列表,或重新评估索引设计。 - 修改关联逻辑:如果后续查询不再通过
studentID关联tblParents,这个索引会完全失去作用,反而占用空间、影响写入。不过从当前表结构来看,这种场景概率极低。 - 减少现有SELECT字段:对索引无负面影响,索引依然是覆盖索引,仅存在少量字段冗余,不会影响查询性能,只是多占用一点存储空间。
内容的提问来源于stack exchange,提问作者kneidels
相关产品推荐
相关产品推荐

