0.写在前面

Lab3的地址:https://15445.courses.cs.cmu.edu/fall2020/project3/
本文主要总结一下在写Lab3需要的基础知识以及Task的解决思路(不公开代码,如果有问题可以留言)。

1.Task #1 - SYSTEM CATALOG

数据库维护一个内部目录(catalog)记录了整个数据库中的table和index信息。
有了catalog,我们就可以从table/index的名字或id,找到这个table/index的指针,以及各种metadata。
在src/include/catalog/catalog.hsrc/include/catalog/catalog.hsrc/include/catalog/catalog.h中实现Table和Index的Create和Get:
CreateTable(Transaction *txn, const std::string &table_name, const Schema &schema)
GetTable(const std::string &table_name)
GetTable(table_oid_t table_oid)

CreateIndex(txn, index_name, table_name, schema, key_schema key_attrs, keysize)
GetIndex(const std::string &index_name, const std::string &table_name)
GetIndex(index_oid_t index_oid),
GetTableIndexes(const std::string &table_name)

第一个任务不是特别的难,但是要注意几点:
1)注意维护几个Hash_table
2)index_Info函数需要一个Index的unique_ptr需要new一个BPlusTreeIndex传入.

TASK #2 - EXECUTORS

实验的整体难度不是特别大,但是要理清执行的逻辑和各类之间的关系。

2.1 executor执行流程

首先是在execution_engine.h中的函数Execute():
第一个参数(AbstractPlanNode *plan):executor对应的planNode。
第二个参数(std::vector *result_set):存放结果。
第三个参数(Transaction *txn):事务。
第四个参数(ExecutorContext *exec_ctx):exec_ctx是当前执行的上下文,记录了bfp,log manager,lock manager,catalog和txnmanager。其中最重要是catalog,catalog中有Tables和Indexs等等。

// execution_engine.h
bool Execute(const AbstractPlanNode *plan, std::vector<Tuple> *result_set, Transaction *txn,ExecutorContext *exec_ctx) {// construct executorauto executor = ExecutorFactory::CreateExecutor(exec_ctx, plan);// prepareexecutor->Init();// executetry {Tuple tuple;RID rid;while (executor->Next(&tuple, &rid)) {if (result_set != nullptr && tuple.IsAllocated()) {result_set->push_back(tuple);}}} catch (Exception &e) {// TODO(student): handle exceptions}return true;}

接着工厂模式ExecutorFactory::CreateExecutor(),根据传入的planNode的类型,使用dynamic_cast将planNode转换成对应类型的planNode(父类指针转换成子类指针),调用对应的executor的构造函数创建executor。然后调用executor的init方法初始化executor,重复执行next方法,next返回true则将结果存入result_set并继续执行next, next返回false 则结束。所以后面的任务就是实现每个executor的init和next方法

// executor_factory.cpp
std::unique_ptr<AbstractExecutor> ExecutorFactory::CreateExecutor(ExecutorContext *exec_ctx,const AbstractPlanNode *plan) {switch (plan->GetType()) {// Create a new sequential scan executor.case PlanType::SeqScan: {return std::make_unique<SeqScanExecutor>(exec_ctx, dynamic_cast<const SeqScanPlanNode *>(plan));}
...
}

AbstractPlanNode
这是所有PlanNode的父类。对应的有一个枚举类PlanType,表示所有可能的PlanNode类型。AbstractPlanNode只有两个成员变量,一个是output_shcema,在Next返回tuple(如果需要返回tuple)时可以根据output_schema选择输出tuple的哪几个column(相当于select)。另一个是vector children_, 里面有所有children的常量指针。

/** PlanType represents the types of plans that we have in our system. */
enum class PlanType { SeqScan, IndexScan, Insert, Update, Delete, Aggregation, Limit, NestedLoopJoin, NestedIndexJoin };
2.2 各个类之间的关系

exec_ctx[bfp, log manager, lock manager, catalog, txnmanager]
catalog:[tablesindexes]
tables:[id,table_metadata]
table_metadata:[shema(表,索引,外键等等), name, table_(table_heap)(pages组成的链表), id]

indexes:[id,index_info]
index_info:[shema, name, index_, id, table_name, key_size]

2.3 SEQUENTIAL SCAN

sequential node继承自abstract node,多了两个私有变量。一个是predicate,是用来过滤不符合条件的tuple。比如where id < 5 就是一个predicate。另一个变量是table_oid_,指明了要扫描的表的id。

  const AbstractExpression *predicate_;/** The table whose tuples should be scanned. */table_oid_t table_oid_;

在2.1中execute的执行流程中,我们首先construct executor,再进行Init(),最后调用Next()获取Tuple.
所以在construct executor时候获得table_meta_data,init()的时候获得table迭代器,table_iterator支持对表顺序扫描,指向当前尚未遍历的第一个tuple。
在Next()函数中我们首先找到当前迭代器指向的第一个符合要求的tuple,然后输出新的tuple。
1)在寻找第一个符号要求的tuple的时候注意,GetPredicate是父类AbstractExpression指针,调用GetPredicate的虚函数Evaluate(),会根据具体的子类类型调用子类的虚函数Evaluate(),返回一个Value类型的结果。调用这个Value类的GetAs函数即可得到该tuple是否满足要求。不满足就继续下一个tuple。
2)在获得新的tuple的时候要注意,并不能直接把table_iterator返回的tuple直接作为结果,因为plan中的OutputSchema可能仅仅是table_iterator返回的tuple的一个projection。

我们可以在Executor_test中一个一个测试样例。

2.4 INDEX SCANS

IndexScan与SeqScan逻辑是类似的,区别在于把TableIterator换成IndexIterator。可以从index_info获得table_name_。

2.5 INSERT

Insert操作是将元组添加到表中。
这里需要注意我们首先需要根据InsertPlanNode的类型来判断child是否有tuple需要插入。
例子:INSERT INTO empty_table2
(SELECT colA, colB FROM test_1 WHERE colA > 500)
【 child对应select】
每次获得一个tuple之后需要将tuple同步到所有的index中,调用index_->InsertEntry。

//如果将insert值直接嵌入到计划中,则为true;
//如果是child plan提供tuple,则为false
plan_->IsRawInsert()
2.6 Update

Update操作是修改指定表中的tuple。
1)通过child_executor_获取下一个需要更新的tuple。
2)调用GenerateUpdatedTuple得到新生成的tuple。
3)调用tableHeap的updataTuple在表中更新tuple,再在所有的索引中删除原来的tuple,插入新的tuple,返回tuple的RID即可。

2.7 Delete

Delete是删除指定表中的tuple。
1)通过child_executor_获取下一个需要删除的tuple。
2)通过table的MarkDelete来标记tuple。然后更新 tnx write set.(这里MarkDelete的意思是使tuple invisable,并不真的删除它。只有在事务提交的时候才真的删除。这样如果事务还没提交就abort了,回滚时只需要将mark的标志撤销)
3)更新索引。

2.8 Join

例子:

SELECT test_1.colA, test_1.colB, test_2.col1, test_2.col3
FROM test_1 JOIN test_2 ON test_1.colA = test_2.col1 AND test_1.colA < 50

2.8.1 Nested Loop Join
Nested Loop Join的实现就是从遍历两张表,对于外查询的每个Tuple在内表中遍历查看是否有相等。

2.8.2 Index Nested Loop Join
Index Nested Loop Join是利用innerTable的索引查找符合 JOIN 条件的。

2.9 Aggregation

例子:

SELECT COUNT(colA), SUM(colA), min(colA), max(colA) from test_1;

可以直接使用官方已经写好的SimpleAggregationHashTable来实现。

CMU 15-445/645 Lab3-Query Execution相关推荐

  1. CMU 15-445/645-Note6-执行篇-Query Execution

    0.写在前面 based on CMU 15-445/645 2020fall, Lecture #12-Lecture #13. 1:执行模型(PROCESSING MODEL) DBMS 的执行模 ...

  2. 2021年秋季版 CMU数据库15-445/645 Note1~4

    2021年秋季版 CMU数据库15-445/645 Note翻译 NOTE 这也就是说这并不是一门教你如何使用数据库去构建应用程序.网站或者其他东西课,也不是一门教你如何去管理和部署数据库的课. 我们 ...

  3. Morsel-Driven Parallelism: 一种NUMA感知的并行Query Execution框架

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可. 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权. 引言 一段时间前看到OSAPP中p ...

  4. Query execution was interrupted

    MYSQL Error Error number: 1317; Symbol: ER_QUERY_INTERRUPTED; SQLSTATE: 70100Message: Query executio ...

  5. Adaptive Query Execution: Speeding Up Spark SQL at Runtime

    This is a joint engineering effort between the Databricks Apache Spark engineering team - Wenchen Fa ...

  6. 2021 CMU-15445/645 Project #3 : Query Execution

    0 介绍 21年秋季的15445第3个Project是要完成一些执行器(executor)来实现一些数据库操作比如遍历.插入.更新.删除.连接等等.虽然算法难度上不如Project2,但是需要阅读大量 ...

  7. MIT6.830 Lab3 Query Optimization 实验报告

    一.实验概览 lab3实现的是基于代价的查询优化器,以下是讲义给出的实验的大纲: Recall that the main idea of a cost-based optimizer is to: ...

  8. Filter Representation in Vectorized Query Execution论文笔记

    概览 这篇文章向我们展示了在向量化查询执行引擎里的两种filter representation(bitmap以及select vectors)和两种执行策略:1. Full, 不管有多少active ...

  9. ClickHouse之Distributed Query Execution

    原文地址:https://clickhouse.yandex/docs/en/development/architecture/ 集群中的所有节点都是彼此独立的,当你在集群中的一个节点或者多个节点创建 ...

  10. 执行引擎(Query Execution Engine),返回结果

    OK,存储引擎分析完了,它是我们存储数据的形式,继续第二个问题,是谁使用执行计划去操作存储引擎呢? 这就是我们的执行引擎,它利用存储引擎提供的相应的API 来完成操作. 为什么我们修改了表的存储引擎, ...

最新文章

  1. 安装linux系统报softlock,soft lockup 解决思路
  2. Zepto 与 jQuery 的区别 小结
  3. chameleon 算法_为了简单起见,Arquillian Chameleon
  4. HDU 4990 Ordered Subsequence --数据结构优化DP
  5. Maven笔记——依赖管理
  6. 一步步编写操作系统 08 bios跳转到神奇的内存地址0x7c00
  7. 前端请求接口post_接口自动化测试-WEB资讯专栏-DMOZ中文网站分类目录
  8. element的表格index自定义_vue+element-ui实现表格编辑的三种实现方式
  9. 最新MyEclipseIDEAWebStorm安装 激活
  10. Unity3D实践4:带有出入特效的提示框
  11. Android Studio 查询RecyclerView最新依赖方法
  12. LINUX SHELL脚本多行注释
  13. 蚂蚁金服 Service Mesh 渐进式迁移方案|Service Mesh Meetup 实录
  14. 布客·ApacheCN 编程/后端/大数据/人工智能学习资源 2022.2
  15. Mysql的INTERVAL()函数和INTERVAL关键字
  16. 第二讲:云分类及服务模式
  17. 10种食物 让你快乐每一天
  18. C++基础学习笔记(五)——核心编程PART3
  19. Centos搭建服务
  20. 6-1 Numerical Summation of a Series (40分)

热门文章

  1. 【渝粤题库】陕西师范大学180105 推销策略 作业(高起专)
  2. 「管理数学基础」2.2 泛函分析:压缩映射与巴拿赫不动点定理
  3. 基于ise14.7中的cmd设计
  4. 如何使用Gerber View 软件测量孔径?
  5. Zstack 鼎阳SDS6204示波器和Archiver Appliance的重度测试2
  6. 区块链开源项目Asch源码初探
  7. 计算机图形学台灯光照代码,光照控制自动调光台灯工作原理及设计
  8. 华为、小米、红米、魅族、oppo、三星、vivo安卓手机解除账户锁
  9. MMPOSE代码教学
  10. 万国数据登陆纳斯达克:选择海外上市的2个原因