# Utils
## JoinHashMap
- 映射
- Key: hash value (根据 join on 表达式计算)
- Value:row index(第几行)
- 例如: `1 -> [3,6,8]` ,表示第 3,6,8 行的 hash 值为 1
- Hash 值一样不意味着匹配,会进一步检查(equal_rows_arr)
- 结构:
- map: `RowTable<(u64, u64)>`,存储 (hash_value, row_index)
- 相同hash值的话,存储最后插入的 row index
- next: `Vec<u64>`, 冲突链,大小跟总共有多少行一样。
- row index 以 1 为起始,0 表示空。
- 写入冲突解决:
- 当前 map 中 存储了 (h, i),新插入第 j 行的 hash 值也是 h 的话
- `next[j] = i`, map 更新写入 (h, j)
- 读取 h 的所有 row indices
- 初始:读取 map 拿到 j, 然后读取 `next[j]` 得到 i
- 循环:读取 `next[j]`得到下一个 row index,依次类推。直到读到 0 结束。
- 冲突链的下一个 row index 就在是`next[cur]`
## JoinHashMapType trait
- **get_matched_indices**
- iter:item是 (usize, u64) 即 (row_index,hash_value)
- 返回值
- input_indices:针对每个 hash 匹配的 rows,返回对应的 input row index(自身)
- match_indices:hash 匹配到的 row indices
- 两个 indices 大小一样。
- 只是 hash 匹配,需要进一步检查是否 value 真正相等。
- **get_matched_indices_with_limit_offset**
- 多了 limit 和 offset
- 可以从 offset 作为起点,只匹配 limit 个
---------
# HashJoinExec
## Rust doc
- 多 partition 并行 equi join
- **Join 表达式**:根据 join.on 条件,如 `col1 = col2`
- **Filter 表达式**:join 后可以应用 filters(可选地),无法下推到 inputs 的 Non-equality 谓词
- Build side & Probe side
- 小的 input 应该放到 build side,来减小 hash table 的大小。
- 当前固定左边是 build side, 右边是 probe side
- 执行步骤:
1. **build 阶段**:从 build side input 创建 hashtable,并将所有 record batches 拼成一个大的 batch
- hash table 是一个 **LIFO** 的结构,让 row index 小的在上面,probe 时可以维持 build-side input 的顺序。row index 小最后插入到 hashtable 中。
2. **probe 阶段**:流式执行,检查 hashtable 是否存在匹配。
---------