SQL Server的三种物理连接之Hash Join(三)

简介

hash join icon

在 SQL Server 2012 在一些特殊的例子下会看到下面的图标:

batch hash table build icon

Hash Join分为两个阶段,分别为生成和探测阶段。

首先是生成阶段,将输入源中的每一个条目经过散列函数的计算都放到不同的Hash Bucket中,其中Hash Function的选择和Hash Bucket的数量都是黑盒,通常来讲,查询优化器都会使用连接两端中比较小的哪个输入集来作为第一阶段的输入源。

接下来是探测阶段,对于另一个输入集合,同样针对每一行进行散列函数,确定其所应在的Hash Bucket,在针对这行和对应Hash Bucket中的每一行进行匹配,如果匹配则返回对应的行。    

通过了解哈希匹配的原理不难看出,哈希匹配涉及到散列函数,所以对CPU的消耗会非常高,此外,在Hash Bucket中的行是无序的,所以输出结果也是无序的。

示例演示:

IF OBJECT_ID('dbo.Tbl10') IS NOT NULL DROP TABLE dbo.Tbl10;
CREATE TABLE dbo.Tbl10(
  Id INT IDENTITY(1,1),
  Val INT,
  Fill CHAR(7000) NOT NULL DEFAULT REPLICATE('Fill',1750)
);
 
IF OBJECT_ID('dbo.Tbl100') IS NOT NULL DROP TABLE dbo.Tbl100;
CREATE TABLE dbo.Tbl100(
  Id INT IDENTITY(1,1),
  Val INT,
  Fill CHAR(7000) NOT NULL DEFAULT REPLICATE('Fill',1750)
);
 
INSERT INTO dbo.Tbl10(Val)
SELECT TOP(10) 1+ROW_NUMBER()OVER(ORDER BY (SELECT 1))%100
FROM sys.all_columns A, sys.all_columns B, sys.all_columns C;
 
 
INSERT INTO dbo.Tbl100(Val)
SELECT TOP(100) ROW_NUMBER()OVER(ORDER BY (SELECT 1))
FROM sys.all_columns A, sys.all_columns B, sys.all_columns C;
 
SELECT index_type_desc, alloc_unit_type_desc, index_depth, page_count, record_count
FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID('dbo.Tbl10'),NULL,NULL,'SAMPLED');
 
SELECT index_type_desc, alloc_unit_type_desc, index_depth, page_count, record_count
FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID('dbo.Tbl100'),NULL,NULL,'SAMPLED');

 使用hash join执行下面查询

SET STATISTICS IO ON;
GO
SELECT * 
FROM dbo.Tbl100 A
INNER HASH JOIN dbo.Tbl10 B
ON A.Val = B.Val;
GO
SET STATISTICS IO OFF;

 

查看统计信息:

Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Tbl10'. Scan count 1, logical reads 10, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Tbl100'. Scan count 1, logical reads 100, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

优缺点:

•所有逻辑连接类型都可以处理。

•它确实需要一个相当大的内存量,足够大,以适应整个左侧输入。(可能会在tempdb中)

•在创建哈希索引的整个过程中,没有一行将返回。

在连接条件中至少有一列需要使用一个相等的比较。

因为昂贵的建立阶段,这是最资源密集的连接算法。然而,一旦哈希表是建立的,这个连接算法可以很快。对于没有可用的索引的大表,在探测阶段的时间节省将超过建设阶段的额外费用。然而,记住,因为大量的内存需求,只有极少数的这些可以运行在同一时间。

posted @ 2015-08-29 23:51  行千里  阅读(1142)  评论(0编辑  收藏  举报