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

多对一关系下TSQL Join内部实现及重复值连接效率问询

关于重复值连接的执行效率问题解答

嘿,这个问题问到点子上了,很多人都会好奇SQL Server在处理重复连接键的时候会不会做优化,我来给你详细拆解下~

核心问题:SQL Server会对每个重复的'Luke'都执行连接吗?

答案是:取决于执行计划选择的连接类型,默认情况下优化器不会主动先对左表(@tmp)去重再连接,但不同的连接策略会带来不同的执行逻辑:

1. 哈希连接(Hash Join)

这是小表连接时很常见的选择。SQL Server会先把右表(#test)的所有数据加载到内存,构建一个哈希表(以textval为键),然后遍历左表(@tmp)的每一行,用textval去哈希表中快速匹配。

  • 不管@tmp里有多少个重复的'Luke',哈希表只会构建一次,所有重复值都是复用同一个哈希表做查找,不会重复读取#test,效率很高。

2. 嵌套循环连接(Nested Loops Join)

这种连接类型的行为分两种情况:

  • 如果#test的textval字段有索引:第一次处理'Luke'时,会通过索引查找匹配的行;后面的4个'Luke'会触发重绕(Rewinds)——也就是复用之前的查找结果,不需要再去#test里重新查询。这时候执行计划里的重绕次数会是4,重新绑定次数为0。
  • 如果#test的textval没有索引(就像你的例子里一样):每处理@tmp的一行,都要全表扫描一次#test,5个'Luke'就会扫5次#test,效率很低。

3. 合并连接(Merge Join)

如果两张表都按textval排序(或者有排序后的索引),优化器会选择合并连接。它会同时遍历两个表的排序结果,匹配相同的textval,重复的键会一次性处理,不会重复扫描#test。

怎么从执行计划里判断?

你提到执行计划里重绕/重新绑定次数为0,这大概率说明优化器选择了哈希连接或者合并连接:

  • 哈希连接:查看运算符属性里的「构建次数」,应该是1,代表只构建了一次哈希表。
  • 嵌套循环连接:如果重绕次数大于0,说明复用了之前的查询结果;如果重绕次数为0且没有索引,那就是每次都重复扫描右表了。

要不要手动优化?

如果你的@tmp数据量特别大,重复值很多,可以手动先去重再连接,比如:

WITH tmp_distinct AS (
    SELECT DISTINCT textval FROM @tmp
)
SELECT tmp.textval, t.ID 
FROM @tmp tmp
LEFT JOIN tmp_distinct td ON tmp.textval = td.textval
LEFT JOIN #test t ON td.textval = t.textval;

这样#test只需要和去重后的小数据集连接,再关联回原@tmp,能减少连接的总次数。但如果数据量不大,优化器的默认选择已经足够高效,不需要额外操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:24:30