SQL查询性能优化:该场景下用UNION替代WHERE子句中的OR是否可行?
SQL查询性能优化方案
核心优化方案验证
你提出的将WHERE子句中的OR替换为UNION的思路完全可行,是当前场景的核心优化方向:原有OR逻辑会导致数据库无法命中Tool表的联合索引,需要全表扫描匹配两种分支条件,拆分后两个独立查询可以各自命中索引,大幅降低数据扫描量。
额外优化点
- 移除子查询中的字段函数转换:将
convert(datetime, subTool.DateTime, 120) < @ToolDateTime调整为直接匹配subTool.DateTime < @ToolDateTime,提前对@ToolDateTime做格式适配即可,避免字段上的函数运算导致索引失效。 - 新增覆盖式联合索引:
Tool表新增索引(CustomerId, ToolTypeId, ToolId, Is_Active, InterviewId, DateTime, StartDate, EndDate, Id),覆盖所有查询、排序字段,实现索引覆盖无需回表查询。 - 子查询结果提前提取:将
OR分支中的子查询提前提取为变量,避免重复执行计算。 - 替换
UNION为UNION ALL:两个查询分支通过InterviewId = @InterviewId和InterviewId != @InterviewId实现互斥,不存在重复数据,无需UNION的去重步骤,性能可进一步提升。 - 避免
SELECT *写法:按需指定返回字段,减少数据传输开销,也更容易实现索引覆盖。
优化后参考SQL
-- 提前提取子查询结果 DECLARE @TargetToolId INT SELECT TOP 1 @TargetToolId = SubTool.Id FROM Tool SubTool INNER JOIN Interview subInterview ON subInterview.Id = SubTool.ToolId WHERE SubTool.ToolTypeId = @ToolTypeId AND SubTool.Is_Active = 1 AND SubTool.InterviewId != @InterviewId AND SubTool.ToolId = @ToolId AND SubTool.CustomerId = @CustomerId AND SubTool.DateTime < @ToolDateTime ORDER BY SubTool.DateTime DESC, SubTool.StartDate DESC, SubTool.EndDate, SubTool.Id DESC -- 拼接两个查询分支 SELECT Tool.*, Interview.* FROM Tool INNER JOIN Interview ON Interview.Id = Tool.InterviewId WHERE Tool.ToolTypeId = @ToolTypeId AND Tool.Is_Active = 1 AND Tool.InterviewId = @InterviewId AND Tool.ToolId = @ToolId AND Tool.CustomerId = @CustomerId UNION ALL SELECT Tool.*, Interview.* FROM Tool INNER JOIN Interview ON Interview.Id = Tool.InterviewId WHERE Tool.Id = @TargetToolId ORDER BY StartDate, Id
内容的提问来源于stack exchange,提问作者JoãoEs
相关产品推荐
相关产品推荐

