2014-09-30 72 views
1

我是Hive和SQL的新手,所以這可能是一個簡單的問題,但我還沒有找到解決方案與幾個小時的網頁搜索。如何在Hive(HQL)查詢中重用表達式?

我正在寫我的select查詢中的表達式,我想在select查詢的其他列中使用該查詢。例如,

select (-b + sqrt(b*b - 4*a*c))/(2*a), (-b - sqrt(b*b - 4*a*c))/(2*a) from tablename; 

除了重新計算判別(sqrt(b*b - 4*a*c))的輕微的效率低下,這樣的事情是很難給人閱讀的。如果這是一個程序,我的部分結果disc = sqrt(b*b - 4*a*c)存儲這樣的:

select [somehow assign disc] (-b + disc)/(2*a), (-b - disc)/(2*a) from tablename; 

我已經能夠找到的「臨時變量」和「表變量」看起來像被保存在一個單獨的查詢到一箇中間表並摺疊到主查詢中,這對於那些應該沒有開銷的東西來說是很大的開銷。如果Hive想要,它可以在提交查詢之前擴展我所有的表達式(儘管我更喜歡它實際上避免重新計算)。

我在找什麼名字的東西?我怎樣才能重寫上面的例子只顯示sqrt(b*b - 4*a*c)一次,只提交一個map-reduce作業(沒有中間臨時表)?

(我的實際情況是更爲複雜和計算密集型的。)

回答

1

如果這個點是不是每次使用光盤的時間重寫整個代碼,你可以創建一個Hive UDF(用戶自定義函數)。 我不確定函數結果是否被緩存/如果對於具有相同參數的多個函數調用進行任何優化。

如果該點是計算的 「盤」 的結果僅由線一次,就可以使用common table expression

與Q1爲(選擇SQRT(B * B - 4 * A * C)爲(-b + disc)/(2 * a),(-b-disc)/(2 * a);從表名中選擇(-b + disc)/

也可以使用子查詢

選擇(-b +光盤)/(2 * A),(-b - 光盤)/(2 * A)從

(選擇的sqrt(b * b - 4 * A * C)作爲盤,A,b,C從表名)Q1


UPDATE:

我比較了3個查詢(選擇重新計算,CTE和子查詢)和執行時間大致相同(18,91,18,78,18,94)的性能。

Hive執行引擎似乎很聰明!

因此,您可能關心的唯一考慮因素是代碼的可讀性。(除非你的測試,在一個更復雜的過程顯示,否則,我會很高興聽到)

+0

謝謝,雖然我把這個答案是,「你不能做你想做的事情,而不寫一個UDF「。當然,如果我編寫UDF,我可以完成所有我習慣的編程工作,比如分配變量並重用它們。這個'q1'或者是磁盤上的臨時表(爲了漂亮的打印而花費太多),或者Hive認識到兩個'select'語句是鏈接映射操作,可以在評估之前進行組合。我會通過實驗嘗試一下,看看是否會有很大的性能影響。 – 2014-10-01 16:45:26

+0

我更新了我的答案。在我的測試中,子查詢/ CTE沒有在磁盤上實現,並且只有一個映射器。 – jbaptiste 2014-10-02 10:09:32