说,我们有这样的查询:
select a.*,b.* from a join b on a.col1=b.col1 and len(a.col1)=10
假设上面的查询使用Hash Join并且有一个残差,则探测键将为col1,残差将为len(a.col1)= 10.
但是在通过另一个例子时,我可以看到探针和残差都是同一列.以下是我想说的内容:
查询:
select * from T1 join T2 on T1.a = T2.a
执行计划,突出显示探测和残差:
测试数据:
create table T1 (a int,b int,x char(200)) create table T2 (a int,x char(200)) set nocount on declare @i int set @i = 0 while @i < 1000 begin insert T1 values (@i * 2,@i * 5,@i) set @i = @i + 1 end declare @i int set @i = 0 while @i < 10000 begin insert T2 values (@i * 3,@i * 7,@i) set @i = @i + 1 end
题:
探针和残留物如何成为同一列?为什么sql Server不能仅使用探测列?为什么必须使用相同的列作为残差来再次过滤行?
测试数据的参考:
解决方法
如果连接在单个列上,类型为tinyint,smallint或integer *,并且如果两个列都被约束为NOT NULL,则哈希函数是“完美的” – 意味着没有机会发生哈希冲突,并且查询处理器不必再次检查值以确保它们真正匹配.
否则,您将看到残差,因为哈希桶中的项目将进行匹配测试,而不仅仅是哈希函数匹配.
您的测试没有为列指定NULL或NOT NULL(顺便说一下,这是一种不好的做法),因此您似乎使用的数据库中默认为NULL.
更多信息,请参阅Dmitry Pilugin在Join Performance,Implicit Conversions,and Residuals和Hash Join Execution Internals发表的文章.
*其他限定类型是bit,smalldatetime,smallmoney和(var)char(n),用于n = 1和二进制排序规则