字节跳动青训Day2
[传送门](【第三届字节跳动青训营|刷题打卡】DAY2 - 掘金 (juejin.cn))
数据库Join算法,之前没有学过。
-
Nested Loop Join 嵌套循环联合
MySQL只支持NLJ,NLJ故名思意,就是通过嵌套的方式,用两层循环,第一张表作为Outter Loop外循环,第二张表作为inner Loop内循环,找到Outter Loop中满足条件的。NLJ分为三种:
- Simple Nested Loop Join(SNLJ)这个在数据库中永远不会使用
//伪代码
for (r in R) {
for (s in S) {
if (r satisfy condition s) {
output <r, s>;
}
}
}
一看就很暴力,暴力笛卡尔积,时间复杂度O(n*m)
- Index Nested Loop Join(INLJ) INLJ是在SNLJ的基础上做了优化,通过连接条件确定可用的索引,在Inner Loop中扫描索引而不去扫描数据本身,从而提高Inner Loop的效率,时间复杂度O(n)。
而INLJ也有缺点,就是如果扫描的索引是非聚簇索引,并且需要访问非索引的数据,会产生一个回表读取数据的操作,这就多了一次随机的I/O操作。
也就是说内循环走索引,前提是两张表中必须存在索引。
- 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
两点半了,狗命要紧,赶紧睡觉了