跳转至

1.简介

Join是以表为输入,将表进行笛卡尔积并利用Filter过滤输出的操作。

在关系数据库中,通过将表进行拆分,从而减少重复量和冗余信息。Foreign Key就是一种形式。

将表拆分后,通过Join将拆分的表进行合并,从而得到期望的信息。

从数据传输的方面来看,Join有两种实现方式:

  • 传输raw data:优点是运算结束后无需再从表中获取数据,缺点是可能传输开销较大。
  • 传输record id:也称之为late materialization,它只传输必要的数据和record id,在完成Join后再从表中获取数据。该方案的本意是减少传输的开销,但尤其在分布式数据库中,由于不同数据库间通过网络连接,因此效率可能不如传输raw data。

从实现算法来说,JOIN有三种实现方式:

  • Nested Loop Join
  • Sort-Merge Join
  • Hash Join

本文中提到的outer table指的是进行运算的两张表规模较小的表,而inner table为规模较大的表。

2.Nested Loop Join

简单来说就是利用两个for循环对两张表进行循环扫描,从而合并满足条件的tuple。

对于有M个pages、m个tuple的表A和N个pages、n个tuple的表B来说,其复杂度为M+(m*N),含义为表A总共需要取出M个pages,其每个tuple都要令表B取出M次pages。

对于M=1000、m=100,000和N=500、n=40,000的表来说,若pages的大小为4kb,那么这两张表的大小为6MB。

通过计算,其I/O复杂度为500+(40000*1000)=40,000,500,即大约1.1小时。

常见的优化方法是基于利用更大的单位block进行扫描,而不是pages。

假设可缓存B个page,那么利用B-2个page缓存其中一个table,一个page扫描另外一个table以及一个page存储输出。其复杂度为M+(\lceil M/(B-2)\rceil *N)

3.Sort-Merge Join

先对两张表进行排序,利用两个游标指向有序的表,对于匹配的tuple进行合并。

sort R,S on join keys
cursor_R -> R_sorted,cursor_S -> S——sorted
while cursor_R and cursor_S:
    if cursor_R > cursor_S:
        cursor_S ++
    if cursor_R < cursor_S:
        cursor_R ++
    elif cursor_R == cursor_S:
        emit
        cursor_S ++

对于两个阶段,其复杂度为:

  • Sort Table R:O(2\times N \times\lceil log_KM \rceil)
  • Sort Table S:O(2\times N \times\lceil log_KN \rceil)

  • Merge:O(M+N)

4.Hash Join

对outer table建立哈希表,然后对inner table进行顺序扫描,所有与inner table匹配的值都可以在哈希表的其中一个分区找到。

常见优化:在对inner table扫描时,利用布隆过滤器提前查询哈希表中是否有该key。

5.Grace Hash Join

Hash Join中采用对outer table建立哈希表是因为需要尽可能在内存中存放outer table,否则会在磁盘中产生许多随机I/O。

如果outer table过大,Hash Join的性能就不是很理想。

Grace Hash Join通过对inner table也建立哈希表Hash Join的在该场景下进行了优化。

Grace Hash Join的算法很简单,通过对inner table和outer table建立哈希表,然后取出两表相同key的bucket,然后对它们进行nested loop join。

6.总结

对于上述介绍的算法,其复杂度与例子对应的时间如下表:

Algorithm I/O Cost Example
Nested Loop Join M+(m*N) 1.3h
Block Nested Loop Join M+(M*N) 50s
Sort-Merge Join M+N+(sort cost) 0.59s
Hash Join 3*(N+M) 0.45s

对于Sort-Merge Join来说,需要通过元数据来判断是否有数据倾斜。同时除非表已经是有序的,此时Sort-Merge Join的性能更好,否则其他情况下,Hash Join的表现都更好。