CMU15445/645 SQL实现(火山模型)

文章介绍了数据库执行器的不同类型及其功能,包括顺序扫描、插入扫描、聚合、嵌套循环连接和索引扫描等。每个执行器详细阐述了其工作原理,如seq_scan.Executor通过迭代器遍历数据,insert_scan.Executor处理插入并考虑索引更新,aggregation.Executor利用哈希表进行分组和聚合计算,nested_loop_join.Executor执行嵌套循环连接操作。
摘要由CSDN通过智能技术生成

 execution函数入口。

参数为:

1、执行计划的指针(来自Plan和Optimizer) 

2、vector存放提取的数据 

3、事务 

4、执行器上下文

 

 execution调用入口:

while函数不断调用Next,将数据存储在vector中。这里的executor是一个基类指针,会自动根据executor类型调用不同算子的Next的函数。

 

seq_scan_executor

我们只需要拿到table_info,就可以拿到第一个page的迭代器,取一个数据把迭代器++,知道迭代器到达end()。

注意这里的迭代器如果到了一个page的末尾会进入到下一个page的头部。

auto SeqScanExecutor::Next(Tuple *tuple, RID *rid) -> bool {
  if (table_iterator_ != table_info_->table_->End()) {
    *tuple = *table_iterator_;
    *rid = table_iterator_->GetRid();
    ++table_iterator_;
    return true;
  }
  return false;
}

 

insert_sacn_executor

插入的时候还需考虑表是否建有索引,若有索引还得同步更新索引信息。所以在Init阶段去拿table和索引信息,在Next阶段调用TableHeap的InsertTuple新增tuple;若有索引信息,调用上一个projcet实现的InsertEntryt添加索引信息。

DeleteExecutor

和插入类似,在Init阶段拿table和索引信息,在Next阶段调用TableHeap的MarkDelete删除tuple和调用DeleteEntry删除索引信息。

Index_scan_executor

类似于seq_scan,也是用迭代器遍历,只是这里索引迭代器拿到的是rid,并不是真实要的数据。还需要GetTuple从表中拿到数据再返回。

auto IndexScanExecutor::Next(Tuple *tuple, RID *rid) -> bool {
  if(iterator_ != index_->GetEndIterator()) {
    *rid = (*iterator_).second;
    if(table_info_->table_->GetTuple(*rid, tuple, exec_ctx_->GetTransaction())){
      ++iterator_;
      return true;
    }
  }
  return false;
}

Aggregation_executor

 聚合实现的是分组(group by),聚集(count*,count列,min,max,sum)

聚合的模式是先分组列,再聚合列。实现聚合的策略是哈希表,涉及到SimpleAggregationHashTable,需要先实现SimpleAggregationHashTable中的CombineAggregateValues函数。

例如下表:

 

如选择按等级进行分组,则aggregate_key为等级这一列,aggregate_value为姓名和年龄这两列。

 InsertCombine会先给aggregate_key生成初始值,初始值规则为若是count*,则为0,若是其他则为NULL。注意调用CombineAggregateValues并没有使用agg_key,而是使用agg_key对应的内容(参数1)

CombineAggregateValues函数:

 

参数1为已经存在的聚集内容,参数2为新加入的数据。

例如我们在InsertCombine已经插入等级上中的[张三,18],在插入[张麻子,45]时,result为[张三,18]对应的数据(Value可能存的的是一个int,如count*,根据聚合类型所表现的Value不同),input为[张麻子,45]

根据聚集类型,选择对应的处理方式,如count*则是每次插入就将结果+1,需要调用Value的Add函数。

 

Next函数

next函数就是从哈希表的begin()迭代器开始遍历到end,每次输出一行数据

1、先把分组的数据全部放进vector

2.再把聚集的数据放入vector

 再++迭代器即可

注意:如果是空表,即迭代器为end时,则count*返回0,其他都返回NULL

nested_loop_join_executor

select * from a,b where a.id=b.id

嵌套循环链接,实现思路很简单,就是两个循环,用B表的id号依次去匹配A表的id,若能匹配上则合并这一行。

要分为左连接和内连接,左连接如果A表的id号在B表中没有,也要保留这一行,将B表的部分设为NULL。而内连接若没匹配上则不管。

实现方式:因为next只能调一次,所以在init中先用右表调next把数据存在vector中

Next函数:左表去遍历右表进行匹配,注意可能会有多行成功匹配此时不能在第一个匹配上就返回,所以设置了index来表示本次遍历到右边的哪一行。index为0时先用next进行第一个符合条件的行的匹配,若匹配到则更新index,还需要从index开始继续往下找,直到把右表找完

nested_index_join_executor

和嵌套循环连接类似,只是采用索引来进行匹配,不需要遍历,提升了性能。也要分左连接和内连接讨论

sort_executor

Init里把所有数据读完自定义排序就行,Next函数直接一个个输出即可

升序则return a<b,降序 return a>b

 

limit_executor

最简单的,就next里吐limit个数据就行

topN_executor

方法1:sort加limit

方法2:优先级队列实现topN

topN算法:假设要最小的N个数,则搞一个大顶堆,维护大顶堆的size为n,一旦超过N,则弹出堆顶元素,直到所有元素都遍历完,堆里剩下的元素就为最后N个元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值