You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

含OR条件的Inner Join性能优化求助:存储过程返回300万条耗时16分钟

优化带OR条件JOIN的百万级查询方案

这个场景我太熟悉了——JOIN里的OR简直是查询性能的“隐形杀手”,尤其是当数据量达到300万级别时,数据库引擎很难生成高效的执行计划,自然就会拖慢整个过程。针对你的SQL,我给你几个可落地的优化方案:

方案一:拆分OR条件为独立JOIN,用UNION ALL合并结果

你的JOIN条件里的两种情况是互斥的(AD.ID不为空时走第一个条件,为空时走第二个),完全可以拆成两个查询,再用UNION ALL合并结果(比UNION高效,因为不需要去重)。改写后的SQL如下:

SELECT AD.id, AD.[from]
FROM [#Temp1] AD 
JOIN [#Temp2] SS ON AD.Id = SS.Id
JOIN wTable1 WSS WITH(NOLOCK) ON SS.PId= WSS.Id

UNION ALL

SELECT AD.id, AD.[from]
FROM [#Temp1] AD 
JOIN [#Temp2] SS ON SS.Code = AD.Code AND AD.ID IS NULL
JOIN wTable1 WSS WITH(NOLOCK) ON SS.PId= WSS.Id

这样拆分后,数据库可以分别为两个查询路径匹配最优索引,避免了OR导致的索引失效问题,执行效率会有明显提升。

方案二:针对性添加索引

索引是百万级查询的核心优化点,你可以给以下对象添加索引:

  • #Temp1创建包含IdCode的复合索引,比如:CREATE NONCLUSTERED INDEX IX_Temp1_Id_Code ON #Temp1(Id, Code) INCLUDE([from])(INCLUDE返回字段,避免键查找)
  • #Temp2创建包含IdCodePId的复合索引:CREATE NONCLUSTERED INDEX IX_Temp2_Id_Code_PId ON #Temp2(Id, Code) INCLUDE(PId)
  • 确保wTable1Id字段有主键或唯一索引(通常主键默认会建索引,但如果没有的话补上)

另外提醒一句:WITH(NOLOCK)虽然能减少阻塞,但会读到未提交的脏数据,如果你的业务对数据一致性要求高,要谨慎使用。

方案三:优化临时表性能

如果#Temp1#Temp2是临时表,还可以做这些优化:

  • 创建临时表时直接指定索引,而不是事后创建,减少IO开销
  • 如果是SQL Server环境,可以考虑使用内存优化临时表,适合高并发、大数据量的场景,能大幅降低磁盘IO

额外注意点

  • 检查数据库统计信息是否更新:过时的统计信息会让数据库生成错误的执行计划,执行UPDATE STATISTICS语句更新统计信息
  • 确认返回字段只保留需要的:你只需要idfrom,确保没有多余字段,减少数据传输的开销

内容的提问来源于stack exchange,提问作者vinton

火山引擎 最新活动