字节跳动青训Day2

124 阅读2分钟

字节跳动青训Day2

[传送门](【第三届字节跳动青训营|刷题打卡】DAY2 - 掘金 (juejin.cn))

数据库Join算法,之前没有学过。

  • Nested Loop Join 嵌套循环联合

    MySQL只支持NLJ,NLJ故名思意,就是通过嵌套的方式,用两层循环,第一张表作为Outter Loop外循环,第二张表作为inner Loop内循环,找到Outter Loop中满足条件的。NLJ分为三种:

  1. Simple Nested Loop Join(SNLJ)这个在数据库中永远不会使用
//伪代码
for (r in R) {
    for (s in S) {
        if (r satisfy condition s) {
            output <r, s>;
        }
    }
}

一看就很暴力,暴力笛卡尔积,时间复杂度O(n*m)

  1. Index Nested Loop Join(INLJ) INLJ是在SNLJ的基础上做了优化,通过连接条件确定可用的索引,在Inner Loop中扫描索引而不去扫描数据本身,从而提高Inner Loop的效率,时间复杂度O(n)。

而INLJ也有缺点,就是如果扫描的索引是非聚簇索引,并且需要访问非索引的数据,会产生一个回表读取数据的操作,这就多了一次随机的I/O操作。

也就是说内循环走索引,前提是两张表中必须存在索引。

  1. Block Nested Loop Join(BNLJ)两张表上没有索引的时候才会使用的算法 BNLJ在SNLJ的基础上使用了join buffer,会提前读取Inner Loop所需要的记录到buffer中,以提高Inner Loop的效率,时间复杂度O(n*m),但是从缓存中读取会更快。
for (r in R) {
    for (sbu in SBuffer) {
        if (r satisfy condition sbu) {
            output <r, s>;
        }
    }
}
  • Hash Join 哈希联合

MySQL 是不支持 Hash Join的,oracle数据库支持

Hash Join就是根据Join Key的哈希值建立Hash表,将数据存储在内存中,外表在通过Hash O(1)查找

我们先看一下这样一条SQL语句

select * from tb1 left join tb2 where tb1.id = tb2.id

现在假设这个 Join 采用的是 hash join 算法,整个过程会经历三步:

  • 1. 确定 Build Table 以及 Probe Table: 这个概念比较重要,Build Table 使用 join key 构建 Hash Table,而 Probe Table 使用 join key 进行探测,探测成功就可以 join 在一起。通常情况下,小表会作为 Build Table,大表作为 Probe Table。此事例中 item 为 Build Table,order 为 Probe Table。

  • 2. 构建 Hash Table: 依次读取 Build Table(item)的数据,对于每一行数据根据 join key(item.id)进行 hash,hash 到对应的 Bucket(桶),生成 hash table 中的一条记录。数据缓存在内存中,如果内存放不下需要 dump 到外存。

  • 3. 探测: 再依次扫描 Probe Table(order)的数据,使用相同的 hash 函数映射 Hash Table 中的记录,映射成功之后再检查 join 条件(item.id = order.i_id),如果匹配成功就可以将两者 join 在一起

  • Sort Meger Join

TBD

两点半了,狗命要紧,赶紧睡觉了