You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

咨询问题

  1. 该索引是否建议创建?
  2. 创建后有何弊端?
  3. 若后续修改查询或新增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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:45:54