QUERY EXECUTION
再开始这个实验之前首先要搞懂几个类的定义和方法
Catalog.h
Catalog
用来维护一个数据库的元信息,包括表的信息,列的信息,索引的信息,用户和许可权等。在catalog.h
文件中主要包含一下几点信息:
std::unordered_map<table_oid_t, std::unique_ptr<TableInfo>> tables_; //用来维持一个table_id 到 TableInfo 之间的映射
/** 用来表示table的名字到table_id的映射 */
std::unordered_map<std::string, table_oid_t> table_names_;
/** 创建一个table_id */
std::atomic<table_oid_t> next_table_oid_{0};
/** 用来维持一个index_id 到 indexinfo的映射**/
std::unordered_map<index_oid_t, std::unique_ptr<IndexInfo>> indexes_;
/** Map table name -> index names -> index identifiers. */
std::unordered_map<std::string, std::unordered_map<std::string, index_oid_t>> index_names_;
std::atomic<index_oid_t> next_index_oid_{0};
其中TableInfo
类用来维持一个表的基本信息:
Schema schema_; //一个表的schema
const std::string name_; //一个表的名字
std::unique_ptr<TableHeap> table_; //一个表的迭代器
const table_oid_t oid_; //一个表的id
IndexInfo
类用来维持一个索引的基本信息:
Schema key_schema_; //一个key对应的schema
std::string name_; //一个索引的名字
std::unique_ptr<Index> index_; // 一个指向索引的指针
index_oid_t index_oid_; //索引的id
std::string table_name_; //拥有这个索引的表名
const size_t key_size_; //索引的大小
在Catalog
类中我们通过:
TableInfo *CreateTable(); //创建一个表
TableInfo *GetTable(); //获取一个表
IndexInfo *CreateIndex(); //创建一个索引
IndexInfo *GetIndex(); //获取索引
Column.h
用来表示一个表格的一个列的信息。
std::string column_name_; //列的名字
TypeId column_type_; //该列所存储的值的类型
uint32_t fixed_length_;
uint32_t variable_length_{0};
uint32_t column_offset_{0}; //column在一个tuple中的偏移量
const AbstractExpression *expr_; //用来创建这个列的表达式
Schema.h
schema.h
类用来存储一个表格中所有的列。
/** All the columns in the schema, inlined and uninlined. */
std::vector<Column> columns_; // 一个shcema对应的全部列
/** @return all the columns in the schema */
const std::vector<Column> &GetColumns() const { return columns_; }
const Column &GetColumn(const uint32_t col_idx) const { return columns_[col_idx]; }
AbstractExpression.h
AbstractExpression.h
类表达式类是一个虚基类,用来提供各个类的接口。
Value Evaluate
用来返回一个tuple
对应schema
的value
Value EvaluateJoin
返回一个join
过后的value
Value EvaluateAggregate(const std::vector<Value> &group_bys, const std::vector<Value> &aggregates)
返回一个按照group_bys
分组聚合之后的value
表达式类,用来存储一个表达式树中的节点。这个类派生出了一下几个子类:
ComparisonExpression
: 用于比较,实例化用作一个predicate_
谓词或者是一个having
ColumnValueExpression
: 列元素的的表达值,Evalute
函数用来返回当前tuple
的哪一个value
用来对应要求的coloumn
.AggregateValueExpression
:EvaluateAggregate
函数根据是操作时group_by
操作还是aggrate
操作,返回对应操作的value
。
AbstractExecutor
当SQL语句拆分成一个执行数,每个节点的功能承担者。是所有执行算子的虚基类,主要包含一下两个方法:
void Init()
用来初始化一个算子bool Next(Tuple *tuple, RID *rid)
因为我们采用的是火山模型一次只能返回一个tuple
。Schema *GetOutputSchema()
用来表明该节点执行需要输出哪些列
ExecutorContext
用来维护一个Executor
J节点执行所需要的上下文信息。主要包含一下信息:
/** 当前执行当前executor的事务 */
Transaction *transaction_;
/** 当前executor执行的database的catalog */
Catalog *catalog_;
/** 相关的bufferpoolmanager */
BufferPoolManager *bpm_;
/** 和当前事务有关的事务管理器 */
TransactionManager *txn_mgr_;
/** 执行executor所需要的锁管理器 */
LockManager *lock_mgr_;
AbstractPlanNode
所有执行的PlanNode
的虚基类,用来维护每一个存储节点有关的信息。主要包含一下信息:
const Schema *output_schema_; //当前节点输出的schema
/** 当前节点的子节点 */
std::vector<const AbstractPlanNode *> children_;
比如一个seq_plan
包含:
const AbstractExpression *predicate_
: 扫描满足条件的谓词table_oid_t table_oid
_, 用来扫描的表格的table_id
Value
最小的存储单位,用来表示每一个tuple
对应的列的存储数据。
Tuple
元组,代表一个表里面的一行,存储了一行的value
, 每一个tuple
的长度由表格对应的schema
决定,也就是有多少个列tuple
就有多长。每个tuple
根据其所在的page
和对应的slot
都有一个rid
用来标识每一个tuple
。
// 就是将数据二进制化或者反过来,用于存储
void SerializeTo(char *storage) const;
void DeserializeFrom(const char *storage);
inline RID GetRid(); //获取一个tuple的rid
// 返回数据指针
inline char *GetData();//获取一个tuple的全部数据
// 返回tuple的长度(bits)
inline uint32_t GetLength();
// 返回指定colum_idx位置的值
Value GetValue(const Schema *schema, uint32_t column_idx)
// 根据schema , key_schema,构建当前tuple的一个Key主要用来插入到hash table中
Tuple KeyFromTuple(const Schema &schema, const Schema &key_schema, const std::vector<uint32_t> &key_attrs);
TableHeap
代表一个磁盘中存储的一张表的本身
page_id_t first_page_id_{}; //用来存储当前表的第一个page的pageid
/*一个事务,用来插入一个tuple*/
bool InsertTuple(const Tuple &tuple, RID *rid, Transaction *txn);
bool MarkDelete(const RID &rid, Transaction *txn); // 根据rid删除一个tuple
bool UpdateTuple(const Tuple &tuple, const RID &rid, Transaction *txn); //更新对应的tuple
void ApplyDelete(const RID &rid, Transaction *txn); // 执行删除操作
void RollbackDelete(const RID &rid, Transaction *txn); //txn回滚,回滚删除操作
TableIterator Begin(Transaction *txn); //当前table第一个tuple的位置,通过Page_id迭代查找第一个tuple的位置
TableIterator End(); //最后一个位置的下一个位置
Table_page
在底层的tuple存储到page
里面的存储方式采用sloted_page
的存储方式,分为一个slot_array
里面存储每一个tuple
的指针用来指向tuple
的位置,slot_array
按照从前往后的次序依次递增,tuple
从后往前依次存储,当两者相遇的时候说明一个page
存满了。
/**
** Slotted page format:*
** ---------------------------------------------------------*
** | HEADER | ... FREE SPACE ... | ... INSERTED TUPLES ... |*
** ---------------------------------------------------------*
** ^*
** free space pointer*
** Header format (size in bytes)
标签:std,const,tuple,一个,table,QUERY,EXECUTION,schema From: https://www.cnblogs.com/gxsoar/p/16943108.html