『 CMU-15445 』Project 3 Query Execution

前言

第三个实验需要我们实现一个执行器(并非解释器),我认为这个实验和 project2 来说各有各的难点。project2 难在即使非常清楚了可拓展哈希表的流程,在多线程、各种锁的折腾下还是很容易出错,每一个小 TASK 都需要debug很长时间。而这个 project 难在已经实现的类、及其成员变量非常繁杂,相互之间的调用很不清晰,完全不知道各个变量的具体含义。所以在做这个 project 之前,梳理已给代码非常重要。

TASK #1 - EXECUTORS

整个 project 只有这一个 task,需要我们实现以下9个执行器:

  • 读取:Sequential Scan(顺序扫描)
  • 增删改查: Insert, Update, Delete
  • 其他:Nested Loop Join, Hash Join, Aggregation, Limit, Distinct

思路

在前言中我们提到各种成员变量,包括

Catalog、Tuple、Schema、TableHeap、TableHeapIterator、Value、Column...等待

其每个变量都在具体数据库中有一个对应,我是通过 debug 慢慢摸索出其含义,后来发现 这篇文章 总结非常好,在做第一个执行器(Sequential Scan)的时候强烈推荐结合文章理清楚各个类的交互关系。

提示

说一下我踩的几个坑,应该是我对聚合算子本身不来熟悉,导致一些比较乌龙的错误。

一个是要注意 group by 是可以接多个列的,站在数据库层表示以 n 个完全相同的列进行分组,在代码中体现就是 AggregateKey 的成员变量 group_bys_ 是一个 vector

二是我在看聚合的测试文件时,发现 ValueExpression 必须指定输出列是否为 is_group_by_term。根据执行逻辑如果是则代表其为 group by 的字段,如果不是则代表其为聚合的字段。

比如这样的语句:select count(Id),City from Employee group by City ,前者则为false,后者则为 true。

后来我突发奇想,如果是这样的语句select count(Id),City,Address from Employee group by City ,其中 Address 既不是 group by 的字段,也不是聚合的字段,那该怎么支持呢?

count(ID) City Address
1 Kirkland 722 Moss Bay Blvd.
4 London 14 Garrett Hill
1 Redmond 4110 Old Redmond Rd.
2 Seattle 507 - 20th Ave. E. Apt. 2A
1 Tacoma 908 W. Capital Way

后来想了想在聚合里这个字段也没有意义,如果一个组有多个数据,可能只会随机输出一个,真实情况下我们一般会考虑group_concat:

select count(Id),City,group_concat(Address,' ;') from Employee group by City

count(ID) City group_concat(Address,’ ;’)
1 Kirkland 722 Moss Bay Blvd.
4 London 14 Garrett Hill ;Coventry House Miner Rd. ;Edgeham Hollow Winchester Way ;7 Houndstooth Rd.
1 Redmond 4110 Old Redmond Rd.
2 Seattle 507 - 20th Ave. E. Apt. 2A ;4726 - 11th Ave. N.E.
1 Tacoma 908 W. Capital Way

那这样的话就又得支持新的算子了,虽然感觉上不难… 不过我暂时还没有实现 XD

最后

最重要的一点,请不要使用官方的打包命令,gradescope 上莫名其妙把一堆自带的 GTEST 给检测,其 check-lint G了一大片,后来群里大哥说加上 src/include/storage/page/tmp_tuple_page.h 可以解决,原因位置:

zip project3-submission.zip \
src/include/buffer/lru_replacer.h \
src/buffer/lru_replacer.cpp \
src/include/buffer/buffer_pool_manager_instance.h \
src/buffer/buffer_pool_manager_instance.cpp \
src/include/storage/page/hash_table_directory_page.h \
src/storage/page/hash_table_directory_page.cpp \
src/include/storage/page/hash_table_bucket_page.h \
src/storage/page/hash_table_bucket_page.cpp \
src/include/container/hash/extendible_hash_table.h \
src/container/hash/extendible_hash_table.cpp \
src/include/execution/execution_engine.h \
src/include/execution/executors/seq_scan_executor.h \
src/include/execution/executors/insert_executor.h \
src/include/execution/executors/update_executor.h \
src/include/execution/executors/delete_executor.h \
src/include/execution/executors/nested_loop_join_executor.h \
src/include/execution/executors/hash_join_executor.h \
src/include/execution/executors/aggregation_executor.h \
src/include/execution/executors/limit_executor.h \
src/include/execution/executors/distinct_executor.h \
src/execution/seq_scan_executor.cpp \
src/execution/insert_executor.cpp \
src/execution/update_executor.cpp \
src/execution/delete_executor.cpp \
src/execution/nested_loop_join_executor.cpp \
src/execution/hash_join_executor.cpp \
src/execution/aggregation_executor.cpp \
src/execution/limit_executor.cpp \
src/execution/distinct_executor.cpp \
src/include/storage/page/tmp_tuple_page.h

image-20220828085926610

image-20220828090016838