😉Query Execution
PROJECT #3 - QUERY EXECUTION
这个 project 主要是实现增加对数据库系统的执行计划的支持。需要实现各种 executors,将 query plan 传入 executors 然后执行它们。需要实现下列的 executors:
Access Methods: Sequential Scans, Index Scans
Modifications: Inserts, Updates, Deletes
Miscellaneous: Nested Loop Joins, Index Nested Loop Joins, Aggregation, Limit/Offset
我们需要实现迭代查询处理模型,每个查询计划执行器实现了一个 Init()
函数和 Next()
函数。当 DBMS 调用 executors 的 Next()
函数时,它会返回
一个
tuple
并返回true
没有
tuple
可以再返回时,返回false
TASK #1 - SYSTEM CATALOG
这个 task 不难,主要是实现
src/include/catalog/catalog.h
文件(catalog 维护了数据库的 meta-data)中的要求实现的函数,这些函数与数据库的表和索引有关。
GetTable()
使用std::unordered_map
的at
函数,它会做下标检查,当key
不存在时会抛出异常在
CreateIndex
函数中,创建表的索引时,需要使用 table heap 的迭代器取出每个 tuple,然后使用 tuple 的KeyFromTuple
构造 key tuple 插入到 B+ Tree 中
TASK #2 - EXECUTORS
SEQUENTIAL SCAN
在顺序执行器中,如何保存
table_heap_
的迭代器呢?一直没找到解决方案,因为我先选择在使用std::vector<Tuple>
先保存结果,然后在Next
中一个一个返回。在返回结果时,记得要根据OutputSchema
构造 tuple 返回
INDEX SCANS
通过 B+ Tree 索引,先获得
RID
,然后根据RID
在table_heap_
中得到对应的 tuple
通过
dynamic_cast<BPlusTreeIndex<GenericKey<8>, RID, GenericComparator<8>> *>(indexInfo_->index_.get());
将Index
转成BPlusTreeIndex
类型
INSERT
插入执行器需要区分待插入的数据是
RawInsert
还是来自child_executor_
如果待插入的表存在索引需要使用
KeyFromTuple
构造index_key
,然后将它插入到 B+ Tree 索引中engine 在插入、更新、删除不需要将 tuple 添加到
result_set
中,否则在 test 中会报result_set
不为空的错误
UPDATE
由
child_executor_
的Next
提供 tuple,然后调用GenerateUpdatedTuple
生成待更新的 tuple,最后使用table_heap_->UpdateTuple
进行更新操作
DELETE
由
child_executor_
的Next
提供 tuple调用
table_heap_->MarkDelete
标记这个 tuple 需要删除如果待插入的表存在索引需要使用
KeyFromTuple
构造index_key
,然后在 B+ Tree 索引中将这个 Key 删除
NESTED LOOP JOIN
使用
left_executor
和right_executor
提供的 tuple 进行EvaluateJoin
构造符合条件的 tuple
INDEX NESTED LOOP JOIN
使用索引来进行 Join,这样就不需要扫描整个 inner table。因此我们需要将 outer tuple 转化为对应的
key
,然后在 inner table index 中进行查找。
测试/验证/打包
测试
格式验证
打包
然后前往 https://www.gradescope.com 提交代码
Last updated