了解哈希联接

哈希联接有两种输入:生成输入和探测输入。查询优化器指派这些角色,使两个输入中较小的那个作为生成输入。

哈希联接用于多种设置匹配操作:内部联接;左外部联接、右外部联接和完全外部联接;左半联接和右半联接;交集;并集和差异。此外,哈希联接的某种变形可以进行重复删除和分组,例如 SUM(salary) GROUP BY department。这些修改对生成和探测角色只使用一个输入。

以下几节介绍了不同类型的哈希联接:内存中的哈希联接、Grace 哈希联接和递归哈希联接。

内存中的哈希联接

哈希联接先扫描或计算整个生成输入,然后在内存中生成哈希表。根据计算得出的哈希键的哈希值,将每行插入哈希存储桶。如果整个生成输入小于可用内存,则可以将所有行都插入哈希表中。生成阶段之后是探测阶段。一次一行地对整个探测输入进行扫描或计算,并为每个探测行计算哈希键的值,扫描相应的哈希存储桶并生成匹配项。

Grace 哈希联接

如果生成输入大于内存,哈希联接将分为几步进行。这称为“Grace 哈希联接”。每一步都分为生成阶段和探测阶段。首先,消耗整个生成和探测输入并将其分区(使用哈希键上的哈希函数)为多个文件。对哈希键使用哈希函数可以保证任意两个联接记录一定位于相同的文件对中。因此,联接两个大输入的任务简化为相同任务的多个较小的实例。然后将哈希联接应用于每对分区文件。

递归哈希联接

如果生成输入非常大,以至于标准外部合并的输入需要多个合并级别,则需要多个分区步骤和多个分区级别。如果只有某些分区较大,则只需对那些分区使用附加的分区步骤。为了使所有分区步骤尽可能快,将使用大的异步 I/O 操作以便单个线程就能使多个磁盘驱动器繁忙工作。

注意注意

如果生成输入仅稍大于可用内存,则内存中的哈希联接和 Grace 哈希联接的元素将结合在一个步骤中,生成混合哈希联接。

在优化过程中不能始终确定使用哪种哈希联接。因此,SQL Server 开始时使用内存中的哈希联接,然后根据生成输入的大小逐渐转换到 Grace 哈希联接和递归哈希联接。

如果优化器错误地预计两个输入中哪个较小并由此确定哪个作为生成输入,生成角色和探测角色将动态反转。哈希联接确保使用较小的溢出文件作为生成输入。这一技术称为“角色反转”。至少一个文件溢出到磁盘后,哈希联接中才会发生角色反转。

注意注意

角色反转的发生独立于任何查询提示或结构。角色反转不会显示在查询计划中;角色反转对于用户是透明的。

哈希援助

术语“哈希援助”有时用于描述 Grace 哈希联接或递归哈希联接。

注意注意

递归哈希联接或哈希援助会导致服务器性能降低。如果跟踪中显示许多哈希警告事件,请更新正在联接的列上的统计信息。

有关哈希援助的详细信息,请参阅Hash Warning 事件类