CMU 15445 lab3 QUERY EXECUTION


總覽

這個lab要實現executors,executor負責query plan(就是operator形成的樹)上的operator並執行它們,對於每個executor,需要實現:

對於這個lab,沒有SQL,執行的查詢計划都是寫好的算子樹,並且用的是火山模型,每個算子的執行器(executor)必須實現Next函數,Next函數的執行粒度是一個tuple,也就是每次執行要么返回一個tuple,要么返回一個空指針來表示當前沒有tuple了。那么每個算子executor需要實現一個循環去調用子算子的Next函數

Task#1 SYSTEM CATALOG

catalog存的信息是用來顯示一個database有什么table以及table被存在哪里,其中還存有了table的index

table怎么存的?

復習一下數據庫的存儲模型,每個頁存n個tuple,對於一個table,可以根據key,建立B+樹index,去查詢tuple

可以看到在lab中的實現中,leaf node節點的value就是page_id和slot_num,

那么頁的布局就是slotted page

catalog

catalog需要實現在數據庫中添加tables通過name或則內部標識符table_oid_t取tables,主要是實現:

index的添加

Task#2 EXECUTORS

需要實現sequential scans, index scans, inserts, updates, deletes, nested loop joins, nested index joins, limits with offset and aggregations等算子的executor,每個executor都有兩個方法——Init用來獲取需要scan的tableNext用來迭代讀取table中的tuple當前算子的Next方法就是執行循環去執行子算子的Next,
調用子算子是有慣例的順序。這里的ExecutionEngine采取了工廠模式。
ExecutionEngine中調用ExcutionFactory類去將一個AbstractPlanNode轉化為對應的executor,ExecutorContext保存了一個query的查詢狀態,每次執行一個PlanNode,需要先Init,在execute,

executor的抽象的執行流程

這里拿seq_scan_executor舉例,

  • 該類繼承於AbstractExecutor
  • AbstractExecutor只有一個成員函數ExecutorContext *exec_ctx_AbstractExecutor還兩個純虛函數,Init和Next,這是每個executor都需要實現的
  • ExecutorContext中保存了一個transaction執行一個query時的context,
  • 一個executor還需要planNode,SeqScanPlanNode繼承於AbstractPlanNodeAbstractPlanNode兩個成員變量分別用於限定輸出的schema與其子planNode
  • SeqScanPlanNode有自己的成員變量,分別用於指定其需要掃描的表與掃描表的tuple需要滿足的謂詞
  • 謂詞是AbstractExpression,決定了返回的結果的schema

修改execution_engine.h中的異常處理?

sequential scan

  • Iterator的每次迭代會獲取一個沒有被刪除的tuple不論是在當前Pgae,還找到新的一個Page的第一個沒被刪除的tuple
  • Next函數如果得到了一個tuple,那么返回true,否則false
  • 由於根據predicate計算一個tuple是否可行的Evaluate函數返回的是一個Value類型所以需要GetAs 把Value轉換為bool類型
  • 創建一個column需要使用AbstractExpression類的子類ColumnValueExpression,ColumnValueExpression的Evaluate方法是主要是tuple->GetValue(schema, col_idx_);,Evaluate的第二個schema參數使用來獲取對應列的類型的而GetValue獲取是分別獲取類型與列中的真實數據
    對於varchar類型的數據,由於不定長,所以在tuple的對應column中記錄的是一個四字節的地址,而對於inline的數據(inline應該就是指不是varchar的數據),就放在tuple的對應位置可以猜測存儲的varchar數據的頭4個字節是varcahr數據的大小
  • 傳指針返回值

Index Scans

  • 只考慮Keysize為8的Iterator
  • protected是指基類與繼承類都可以直接訪問
  • 這個predicate檢查所有的列比較合理?

INSERT

  • 需要做兩件事,一是把tuple插入到table中,二是更新tale的所有索引
  • 插入的tuple也分為兩種,一種是原生的tuple,列的值放在InsertPlanNode之中,另一種是從其他table中復制一個tuple插入
  • 用InsertPlanNode中的這個方法判斷是否是原生插入
  • KeyFromTuple可以從一個table的tuple構造一個index entry的key tuple
  • 一個index的keyAttrs是一個數組,表明了table的tuple中的列號
  • 這里涉及了編譯器的一種優化RVO

UPDATE

  • update的子planNode,update的planNode用給定的謂詞去遍歷需要更新的tuple

DELETE

  • Delete需要刪除tuple並在index中刪除index entry,和Update一樣,Delete一定會有一個child executor
  • 為什么不刪除,而是標記,用了實現MVCC嗎?

NESTED LOOP JOIN

此處的join采取一種simple join的join方式

  • join算子,需要分別執行兩個子算子
  • left算子得到的每一個tuple需要與right算子的每一個tuple都判斷謂詞,都如果滿足就輸出一個結果tuple,由於Next函數是一個協程,那么需要保存當前left算子得到的當前tuple,還需要保持一個狀態,表明當前join的left算子是否遍歷完了所有的tuple
  • 一個NestedLoopJoinExecutor尤其對應的OutputSchemaOutputSchema中是一個Column數組,每個Cloumn對象有一個AbstractExpression成員變量那么根據AbstractExpressionEvaluateJoin中的tuple_idx_成員變量可以知道該column來子join的左table還是右table
  • 不過RID有啥用?

INDEX NESTED LOOP JOIN

  • 要求outer table的每一個tuple去與inner的每一個tuple做謂詞判斷,不用謂詞判斷,獲取plan中的指定,通過plan設定的索引的key_schema

  • 點查詢為什么要傳一個vector?

AGGREGATION

  • 在GROUP BY子句后面包含了一個HAVING子句。HAVING類似於WHERE(唯一的差別是WHERE過濾行,HAVING過濾組)HAVING支持所有WHERE操作符。
  • 這個函數用來實現聚合,當一個聚合函數還沒被使用時,將其插入map中並作出合理的初始化這個函數用來做實際聚合操作
  • plan指定了該算子會做哪些聚合
  • 一個plan的有指定的OutPutSchema,而OutPutSchema有一個Cloumn數組,其中每個Column對象指定了用來創建該Column的AbstractExpression,那么每次獲取一個輸出tuple中每一列就是調用OutPutSchema的每一個col的Expression聚類需要把key與val都放到output的tuple中

LIMIT

問題

  • 這個三個參數是干嘛用的?key_schema用來表示key的列的樣子?
  • 一個表可以有很多個index
  • 一個Table就有一個TableHeap,用來存儲Table的頁且采取doubly-linked list的存儲頁的方式
  • 這里返回的是一個Iterator它重載了->
  • 創建索引的時候需要把一個表中的所有的tuple的對於index放到索引數據解構中
  • 一個TablePage刪除tuple的時候,不會真的刪除,用來實現MVCC嗎?
  • 用make_unique會出錯?
  • 測試的時候,找到一個lab2的錯誤,在CoalesceOrRedistribute中Coalesce的時候忘記給sibling_node解鎖了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM