【CMU15-445 Part-11】Join Algorithms

Part11-Join Algorithms

Why Do We Need to Join?

Join其实是关系数据库和范式化表时候所产生的副产物。

也就是说我们范式化表是为了减少冗余信息,而我们使用join就是为了去重建reconstruct 这些原本的tuple

Join Algorithms

主要关注两表的inner equijoin algorithms

通常,较小的表作为左表(left table / outer table)进行join,右表叫做inner table

Join Operators

在叶子节点处对表访问,将表中的tuple作为输入传给父节点的operator。

考虑1. output 查询计划生成树join算子之间传递的是什么 2. 如何判断算法的优劣------Cost Analysis Criteria

  1. 对于两个表R,S的tuple r,s进行join 级联操作,生成一个新的tuple,具体的内容取决于

    1. 查询处理模型 Query processing model (多个tuple)
    2. 存储模型 Storage model ,row / column 存
    3. 具体的query

    关于算子之间的输出传递,可以直接级联的结果进行传递,如果很多列则代价很大,可能进行一个预先的投影操作。还有就是only copy joins keys along with record ids.(特别针对列存) 叫做Late Materialization

  2. I/O Cost Analysis

    计算join过程必须使用的I/O次数来估计成本。只关心join操作的成本,不关心最后输出结果或者其他因素。

    M pages in table R m tuples in R
    N pages in table S n tuples in S

Join VS Cross-Product

cross-product 交叉连接

Join Algorithms

包括Nested Loop Join、Sort-Merge join、Hash Join

Nested Loop Join

cpp 复制代码
for each tuple r in R           // outer table
	for each tuple s in S:        // inner table
		 emit,if r and s match

stupid ! Cost: M + m* N 左表M个pages,然后m个tuple每次都扫描一次右表N个pages,代价就是M+m*N

优化:

  1. 小表作为左表

  2. Block Nested Loop Join

    使用block、page,可以多个tuple一个block/page,让outer table的一个block中所有tuple 完成和inner table中所有tuple的join,再去取下一个inner table的block。

    代价是:M+M*N,这里的话小表就是page少的了 不是tuple少的

  3. 对于outer table使用尽可能多的内存buffer来保存他,即B-2个block 来保存左表,1 block for inner table, 1 block for output result。

    Cost = M + [M / (B-2)] * N

    如果buffer够大可以放开左表,那cost = M+N

  1. 可以避免循序扫描通过使用index来找inner table matches

    1. 使用一个已经存在的index on inner table
    2. build one on the fly(hash table, B+ Tree) 针对join的index 叫做Spooling index. 查询结束删除index

    index不一定就是join on的key,也许join on col A and B,在A上有index也可以用索引探针(Index probe)来进行优化,先找A然后再匹配B列。

    假设C是index查找一个tuple的一个代价,Cost = M + m*C

  2. Sort-Merge Join

    1. 第一阶段---排序:sort both tables on the join keys;可以使用external merge sort或者内存中的快排
    2. 第二阶段---合并:使用游标对排好序的两个表的tuple进行逐个比较,匹配就输出。双指针。

    可能会需要backtracking 回溯操作,回到该值在inner table中第一次出现的地方。只会对inner table进行backtracking。

    Cost =

    最差的情况:outer table中的每个值和inner table中的每个值都相等,每个tuple m都得回溯一次,COST = M * N + SORT COST

    Sort-Merge join 用处:如果有一个或者俩表都on join key排好序了;或者要求order by,需要对结果排序。特别有个索引排好序 且是聚簇索引

  3. Hash Join

    1. hash function是确定的,两个表相同的key hash 结果相同。

    2. 基于hash key来讲outer table拆分成多个分区,付出前期成本来将数据拆分以此让查找或者探测过程更快。即value hash → partition i,R tuple must be in r_i,S tuple must be in s_i。因此R tuples in r_i只需要和S tuples in s_i 比较来进行join

    3. Basic Hash Join Algorithm

      1. Build:循序扫描outer relation 然后pop到hashtable 使用h_1

      2. Probe:对inner relation扫描,使用h_1 将每个tuple进行hash处理;会跳到相同的位置然后看有没有匹配的tuple。

      3. Key:是join操作基于的属性;Value:取决于上层算子的输入。

      4. Hash Table Values

        1. Full Tuple:避免回表IO,但是需要更多内存。
        2. Tuple Identifier:tuple标识符例如record id,适用于列存,
    4. Probe Phase Optimization:再build阶段创建一个bloom filter,在没有查看hash table的情况下可以通过它来判断要查找的tuple是否在这个hashtable中。也叫做sizeways information passing横向信息传递。

      1. Bloom Filter:是一种概率数据结构(Probabilistic DS)(bitmap)用来处理set membership查询(近似成员查询:该key在不在我的集合中)包括操作:insert(x),Lookup(x).好处是可能会假阳性,就是实际不在但是告诉你在,但是不会逻辑上影响正确性,不会假阴性就是在但是告诉你不在,这样就是逻辑错误了这种不会出现。
      2. 具体的优化是构建hash table的时候可能会溢出到磁盘,为key构建一个bloom filter,super small can fit in memory。避免潜在的无用的磁盘I/O
    5. Grace(partition) Hash Join:处理Hash Join don't fit in memory

      1. Build Phase:基于hash key将两张表拆分成多个分区,拆分成两个单独的hash table,outer table和inner table各自有一张hash table。
      2. Probe Phase:比较两张表对应分区的tuples,对匹配的分区进行nested-loop join。

      bucket chain hash table而非linear probe hash table。因为想要相同的数据hash到同一位置或者映射到同一分区。一一匹配去scan。

      都hash到一个bucket就会出问题,用递归分区Recursive Partitioning来解决。使用另外一个hash function h2来建立bucket_r,i。如果有足够buffer,且所有数据都能放在内存中,可以跨分区进行join操作,COST = 3 *(M+N)。分区的时候要对M outertable N innertable进行一轮读和一轮写,probe一轮

Observation

如果DBMS直到outer table的size可以去调整hash table或者buffer size,如果可以都内存就线性hash,如果需要溢出到磁盘就bucket。如果不知道size,可以使用动态hash table(linear extendable hash table)或者允许overflow pages,但是代价会很高。

  1. 什么情况下会不清楚outer table的size? 回答:多个操作之间所产生的临时中间表的size

除非排好序,否则hash join永远比其他join来的好

sorting适合于non-uniform data 或者结果需要排序的情况。

range join anti join?

相关推荐
IvorySQL1 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·1 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德1 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫1 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i2 小时前
完全卸载MariaDB
数据库·mariadb
纤纡.2 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql
jiunian_cn2 小时前
【Redis】渐进式遍历
数据库·redis·缓存
橙露2 小时前
Spring Boot 核心原理:自动配置机制与自定义 Starter 开发
java·数据库·spring boot
冰暮流星2 小时前
sql语言之分组语句group by
java·数据库·sql
符哥20082 小时前
Ubuntu 常用指令集大全(附实操实例)
数据库·ubuntu·postgresql