Author: Sixing Yan
相關(guān)信息
What is BosCollege-SimpleDB? see this.
What is BosCollege-SimpleDB v3.0? see this.
前提提要
這一節(jié)將分析Client端發(fā)送SQL語(yǔ)句垛吗,Server端執(zhí)行SQL語(yǔ)句的全過(guò)程去件。 我們首先從FindMajors.java入手,探究SimpleDB如何執(zhí)行一條select
查詢語(yǔ)句睬澡。本文涉及的文件
Step 0
客戶端執(zhí)行一條SQL語(yǔ)句治宣,將該SQL傳入Server端并獲得結(jié)果集退个,循環(huán)訪問(wèn)結(jié)果集獲取數(shù)據(jù)記錄同眯。
/studentClient/simpledb/FindMajors.java
public class FindMajors {
public static void main(String[] args) {
...
Connection conn = null;
try {
// Step 1: connect to database server
...
// Step 2: execute the query
Statement stmt = conn.createStatement();
String qry = "select sname, gradyear "
+ "from student, dept "
+ "where did = majorid "
+ "and dname = '" + major + "'";
ResultSet rs = stmt.executeQuery(qry);
// Step 3: loop through the result set
while (rs.next()) {
String sname = rs.getString("sname");
int gradyear = rs.getInt("gradyear");
System.out.println(sname + "\t" + gradyear);}
rs.close();
}...}}
Step 1
stage 1-1
(a) pre-request
Obtain sstmt
, an instance of SimpleStatement class
生成一個(gè)SimpleStatement類的變量stmt
,它實(shí)際封裝了RemoteStatement類的變量rstmt
- SimpleStatement(rstmt) <- SimpleConnection.createStatement()
rstmt <= RemoteStatementImpl(rconn)- SimpleConnection封裝了RemoteConnectionImpl
- 實(shí)際執(zhí)行 rstmt:RemoteStatement <- rconn.createStatement()
(b) process
Obtain srs, an instance of SimpleResultSet class
由rstmt
執(zhí)行executeQuery(queryString)芭商,生成由SimpleResultSet封裝的RemoteResultSetImpl類的變量
RemoteStatementImpl.java
public RemoteResultSet executeQuery(String qry) throws RemoteException {
try {
Transaction tx = rconn.getTransaction();
Plan pln = SimpleDB.planner().createQueryPlan(qry, tx);
return new RemoteResultSetImpl(pln, rconn);
}...}
- SimpleResultSet(rrs)<-rstmt.executeQuery(qry)
- rrs <= RemoteResultSetImpl(pln,rconn)
- tx:Transaction <- rconn.getTransaction()
- pln:Plan <- SimpleDB.planner().createQueryPlan(qry, tx)
- rrs has 3 members:
- s:Scan <- pln.open()
- sch:Schema <- pln.schema()
- rconn <- rconn
接下來(lái)我們看SimpleDB.planner().createQueryPlan(queryString, transaction)
完成了哪些工作
stage 1-2
what SimpleDB.planner().createQueryPlan(qry, tx) do?
我們首先看SimpleDB.planner()的工作派草,它負(fù)責(zé)初始化server端的planner類實(shí)例。
/server/SimpleDB.java
public static Planner planner() {
QueryPlanner qplanner = new BasicQueryPlanner();
UpdatePlanner uplanner = new BasicUpdatePlanner();
return new Planner(qplanner, uplanner);
}
這里實(shí)際上是由BasicQueryPlanner類的實(shí)例來(lái)構(gòu)造Query plan的工作(如果是create/update等操作則使用BasicUpdatePlanner類)铛楣。
- pln <- qplanner.createQueryPlan(qry, tx)
- data:QueryData <- Parser(qry).query()
- qplanner <- BasicQueryPlanner(data, tx)
首先使用Parser類(/parse/Parser.java
)來(lái)解析SQL語(yǔ)句近迁,形成QueryTree以方便調(diào)用。
現(xiàn)在探究“創(chuàng)建Plan”到底做了什么簸州。
/planner/BasicQueryPlanner.java
public class BasicQueryPlanner implements QueryPlanner {
public Plan createPlan(QueryData data, Transaction tx) {
//Step 1: Create a plan for each mentioned table or view
List<Plan> plans = new ArrayList<Plan>();
for (String tblname : data.tables()) {
String viewdef = SimpleDB.mdMgr().getViewDef(tblname, tx);
if (viewdef != null) plans.add(SimpleDB.planner().createQueryPlan(viewdef, tx));
else plans.add(new TablePlan(tblname, tx)); }
//Step 2: Create the product of all table plans
Plan p = plans.remove(0);
for (Plan nextplan : plans) p = new ProductPlan(p, nextplan);
//Step 3: Add a selection plan for the predicate
p = new SelectPlan(p, data.pred());
//Step 4: Project on the field names
p = new ProjectPlan(p, data.fields());
return p;}}
總體來(lái)看鉴竭,createPlan()輸入SQL語(yǔ)句的QueryTree(data)以及當(dāng)前的事務(wù)信息(tx),輸出一個(gè)ProjectPlan類的實(shí)例岸浑。
首先搏存,遞歸生成SQL中涉及TablePlan
這一步分別生成SQL中涉及的表的Plan,即是TablePlan
List<Plan> plans = new ArrayList<Plan>();
for (String tblname : data.tables()) {
String viewdef = SimpleDB.mdMgr().getViewDef(tblname, tx);
if (viewdef != null) plans.add(SimpleDB.planner().createQueryPlan(viewdef, tx));
else plans.add(new TablePlan(tblname, tx)); }
如果可以查詢到tblname
相關(guān)的視圖定義矢洲,則遞歸分析該視圖(視圖的定義相當(dāng)于一段select
語(yǔ)句)璧眠,抽取它的最后Plan結(jié)果。如果不能查詢到相應(yīng)的視圖定義(說(shuō)明tblname
指的是一個(gè)table),則為其創(chuàng)建TablePlan類實(shí)例责静。
我們來(lái)看TablePlan類是什么袁滥,
- tplist <- ArrayList<TablePlan>
- tblplan <- TablePlan(tblname, tx), it has two members:
- ti:TableInfo <- SimpleDB.mdMgr().getTableInfo(tblname, tx)
- si:StatInfo <- SimpleDB.mdMgr().getStatInfo(tblname, ti, tx)
-
Attention to mdMgr
- mdMgr:metadataMgr <- SimpleDB.mdMgr()
- mdMgr has 4 members:
- tblmgr -> getTableInfo():TableInfo & createTable():void
- statmgr -> getStatInfo():StatInfo
- idxmgr -> getIndexInfo():Map<String, IndexInfo>
- viewmgr -> getViewInfo():String (一條SQL語(yǔ)句,描述View的定義)
- tblplan <- TablePlan(tblname, tx), it has two members:
接下來(lái)看ProductPlan完成的工作灾螃。
接著將所有的TablePlan類實(shí)例進(jìn)行Product操作题翻。
- ProductPlan(p1:TablePlan, p2:TablePlan)初始化,它包含一個(gè)schema:Schema 成員
- Schema類的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)是HashMap<String,FieldInfo>
- key 是 fieldname:String, value 是 FieldInfo
- FieldInfo類有兩個(gè) 整型 屬性腰鬼,type & length
- 初始化時(shí)嵌赠,完成schema.addAll(p1.schema()) & schema.addAll(p2.schema())
- TablePlan用getTableInfo(tblname,tx)生成 TableInfo(tblname, sch, offsets, reclen)
- TablePlan的schema()返回sch變量
- schema.addAll(p.schema()) 只是把p的schema的HashMap數(shù)據(jù)結(jié)構(gòu)和自己的HashMap合并,
- 所以這里的操作就是把p1和p2的schema合并
- Schema類的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)是HashMap<String,FieldInfo>
第三步是SelectPlan垃喊,完成數(shù)據(jù)的選擇
對(duì)Product后生成的一個(gè)聯(lián)合大表進(jìn)行Selection操作。
- 使用前面生成的Plan類(其實(shí)是繼承了Plan接口的ProductPlan類)生成SelectPlan類
- 初始化SelectPlan(p:ProductPlan, data.pred())
- 這里data:QueryData, data.pred() 返回了一個(gè)Predicate類
最后一步是ProjectPlan
記錄哪些field需要保留袜炕,相當(dāng)于SQL語(yǔ)句中的“select field1, field2, ...” 部分本谜。
約定用語(yǔ)
a->function()
a is the real executor of that function
a<-function()
a is generated by that function
a:A
a is an instance of class A
類的實(shí)例
rstmt RemoteStatement //
rrs RemoteResultSet //
pln Plan //
qry String //
tx Transaction //
ti TableInfo
si StatInfo
sch Schema
s Scan