比如说,我们有一个这样的查询:
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, b 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。
* 其他符合条件的类型是bit、smalldatetime、smallmoney和(var)char(n)对于 n = 1 和二进制排序规则