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

SQL Server中INNER JOIN与WHERE IN性能差异巨大的原因探究

为什么两个逻辑等价的SQL查询性能差10倍?

这事儿核心原因是SQL Server查询优化器对两种写法的执行策略判断完全不同,尤其是有没有用上你给视图创建的聚集索引IX_AlerteVehicule,咱们拆开说:

1. WHERE IN 写法完美贴合视图的索引设计

你的视图AlertesVehicules是带聚集索引的索引视图,索引的最左前缀列是EntiteGestion——这刚好是你要过滤的第一个条件。当你用a.EntiteGestion IN (SELECT value FROM STRING_SPLIT(...))时,优化器一眼就认出可以直接用这个索引的最左列做精准过滤:

  • 先通过聚集索引查找,快速定位到所有符合指定EntiteGestion的行,结果集一下子就缩小了
  • 接着再用CodeAlerte IN ('P08','P09')等条件进一步过滤,后续关联tb_AFFECTATION_SECTION的操作也是基于小结果集,自然速度快(10ms级别)

2. INNER JOIN 写法触发了视图的“展开”,没用到索引视图的优势

当你把STRING_SPLIT的结果用INNER JOIN和视图关联时,优化器没有把这个JOIN条件和视图的过滤逻辑合并,反而选择先展开视图的底层查询:也就是先去扫dbo.Alerte表(输出369000行),再去和拆分后的EntiteGestion列表做关联过滤。这相当于先把大结果集拉出来再筛选,完全浪费了视图上预聚合和聚集索引的优化,所以耗时直接涨到100ms。

另外,这种JOIN写法可能让优化器放弃使用索引视图的预计算结果,转而重新计算视图的底层关联,进一步放大了性能差距。

3. LEFT JOIN的条件也间接影响了执行顺序

两个查询里的LEFT JOIN tb_AFFECTATION_SECTION加上@currentDate <= ISNULL(ase.DateFin, @currentDate)的条件,虽然逻辑上不改变结果,但优化器在处理两种写法时的执行顺序不同:

  • WHERE IN写法:先通过索引视图拿到小结果集,再去关联tb_AFFECTATION_SECTION,关联的数据量小
  • JOIN写法:先拉取视图的全量(或大数量)结果,再去关联,关联的数据量直接大了一个数量级

总结建议

优先保留WHERE IN子查询的写法,它更符合SQL Server优化器的预期,能最大化利用你创建的索引视图。如果一定要用JOIN写法,可以尝试在查询末尾加上OPTION(RECOMPILE),让优化器重新评估执行计划,看看能不能触发索引视图的使用,但通常WHERE IN的写法稳定性更好。

内容的提问来源于stack exchange,提问作者Théophane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:15:58