Hive一條SQL的旅行 一

2021-08-14 18:55:09 字數 3666 閱讀 9366

從今天開始我們從hive原始碼跟蹤一下一條sql語句在hive執行引擎到底做了哪些事情。

整個hive程式的入口是在包org.apache.hadoop.hive.cli下面的

clidriver 類

下面這個就是main 方法

public

static

void

main(string args) throws exception

main 方法裡面呼叫了clidriver裡面的run方法,

這個run 函式最後返回了executedriver方法

public

intrun(string args) throws exception finally

}

跟蹤executedriver方法。從這個方法我們可以看到hive在這裡將語句根據「;」拆分成多條語句,

拆分後的語句都會執行這條語句

ret = cli.processline(line, true)

private

intexecutedriver(clisessionstate ss, hiveconf conf, optionsprocessor oproc)

throws exception

if (line.trim().startswith("--"))

if (line.trim().endswith(";") && !line.trim().endswith("\\;")) else

}return ret;

}

繼續跟蹤processline 方法。這裡主要呼叫了processcmd 方法

processline

public

intprocessline(string line, boolean allowinterrupting)

跟蹤processcmd 方法,這個裡面做了一些判斷,判斷開頭是不是 quit,exit這種退出關鍵字。判斷是不是以source 或者!開頭的。

processcmd

public

intprocesscmd(string cmd) else

if (tokens[0].equalsignorecase("source")) else

if (cmd_trimmed.startswith("!")) else

//省略

}//省略

}

從這裡我們可以到這裡有2條重要的sql語句。其實從這裡我們可以看到最後會執行的語句是processlocalcmd。但是這裡我們要弄清楚proc這個變數是乙個什麼型別。

commandprocessor

proc = commandprocesso***ctory.get(tokens, (hiveconf) conf);

ret = processlocalcmd(cmd, proc, ss);

跟蹤commandprocessor。我們可以看到有乙個 return new driver()。這個我們大概的知道這個返回和driver有關聯的型別,commandprocessor這個型別應該是driver的上一級

commandprocessor

public

static commandprocessor get(string cmd, hiveconf conf)

throws sqlexception

if (isblank(cmd[0])) else

driver drv = mapdrivers.get(conf);

if (drv == null) else

drv.init();

return drv;

}}

接下來我們繼續跟蹤processlocalcmd。從這裡我們可以看到這裡呼叫了driver的run方法

processlocalcmd

int processlocalcmd(string cmd, commandprocessor proc, clisessionstate ss) 

qp.settrycount(trycount);

ret = qp.run(cmd).getresponsecode(); //這裡我們知道直接呼叫了driver的run方法

if (ret != 0)

//省略

}

這裡我們跟蹤一下driver中的run方法,這裡其實主要關注

commandprocessorresponse cpr = runinternal(command, alreadycompiled);

public commandprocessorresponse run(string command)

throws commandneedretryexception

public commandprocessorresponse run()

throws commandneedretryexception

public commandprocessorresponse run(string command, boolean alreadycompiled)

throws commandneedretryexception

sessionstate ss = sessionstate.get();

if(ss == null)

metadataformatter mdf = metadataformatutils.getformatter(ss.getconf());

if(!(mdf instanceof jsonmetadataformatter))

//省略

}

我們繼續跟蹤runinternal方法。這個方法裡面做了一些狀態的判斷,後面又呼叫了compileinternal方法

runinternal

private commandprocessorresponse runinternal(string command, boolean alreadycompiled)

throws commandneedretryexception else

} else

} finally

int ret;

if (!alreadycompiled)

} //省略

}

跟蹤compileinternal方法,這個方法主要做了乙個提交,呼叫了compile方法。

compileinternal

private

intcompileinternal(string command, boolean deferclose) finally

//省略

}

一條SQL的改寫

最近需求中需要實現這樣乙個功能 找主活動是未鎖定的,且已確認的子活動資料,表中資料的分布是這樣的 表中資料存放結構 主活動1 沒鎖定 子活動 主11 已確認 子活動 主22 已確認 主活動2 鎖定 子活動 主21 未確認 子活動 主22 已確認 1用 not exist實現 select t1.at...

一條sql 分類彙總

表結構 stuid stuname stucourse stugrade 001 a 語文 88 002 b 語文 89 003 a 數學 98 004 b 數學 100 005 a 英語 87 006 b 英語 86 mysql select groupid,stuid,stuname,cours...

一條SQL語句研究

現有 select from t where a in 5,3,2,1,8,9,30.假設 a 是主鍵,in裡面的引數是唯一的。現要求輸出的結果集按照 in 提供的引數順序排序。而不是按照a本身的排序規則排序?另 如果不要求使用臨時表或表變數,那麼又有什麼辦法實現。臨時表方案參卡 create ta...