由於 hive 與傳統關系型數據庫面對的業務場景及底層技術架構都有着很大差異,因此,傳統數據庫領域的一些技能放到 Hive 中可能已不再適用。關於 hive 的優化與原理、應用的文章,前面也陸陸續續的介紹了一些,但大多都偏向理論層面,本文就介紹一個實例,從實例中一步步加深對 hive 調優的認識與意識。
1、需求
需求我做了簡化,很簡單,兩張表做個 join,求指定城市,每天的 pv,用傳統的 RDBMS SQL 寫出來就這樣的:
SELECT t.statdate, c.cname, count(t.cookieid) FROM tmpdb.city c JOIN ecdata.ext_trackflow t ON (t.area1= c.cname OR t.area2 =c.cname OR t.area3 = c.cname) WHERE t.statdate>='20140818' and t.statdate<='20140824' AND platform='pc' GROUP BY t.statdate, c.cname;
怎么樣?根據 SQL 看懂需求沒問題吧?
2、非等值 join 問題
然后把這條 SQL 貼到 hive 中去執行,然后你會發現報錯了:
FAILED: SemanticException [Error 10019]: Line 5:32 OR not supported in JOIN currently 'cname'
這是因為 hive 受限於 MapReduce 算法模型,只支持 equi-joins(等值 join),要實現上述的非等值 join,你可以采用笛卡兒積( full Cartesian product )來實現:
SELECT t.statdate, c.cname, count(t.cookieid) FROM tmpdb.city c JOIN ecdata.ext_trackflow t WHERE t.statdate>='20140818' AND t.statdate<='20140824' AND platform='pc' AND (t.area1= c.cname OR t.area2 =c.cname OR t.area3 = c.cname) GROUP BY t.statdate, c.cname;
然后再拿着這條語句執行下。
改寫非等值 join:union all
既然不允許非等值 join,那我們換一下思路,多個子查詢 union all,然后匯總:
SELECT dt, name, count(cid) FROM (SELECT t.statdate dt, c.cname name, t.cookieid cid FROM tmpdb.city c JOIN ecdata.ext_trackflow t ON t.area1 =c.cname WHERE t.statdate>='20140818' AND t.statdate<='20140824' AND platform='pc' UNION ALL SELECT t.statdate dt, c.cname name, t.cookieid cid FROM tmpdb.city c JOIN ecdata.ext_trackflow t ON t.area2 =c.cname WHERE t.statdate>='20140818' AND t.statdate<='20140824' AND platform='pc' UNION ALL SELECT t.statdate dt, c.cname name, t.cookieid cid FROM tmpdb.city c JOIN ecdata.ext_trackflow t ON t.area3 =c.cname WHERE t.statdate>='20140818' AND t.statdate<='20140824' AND platform='pc') tmp_trackflow GROUP BY dt, name;
造成這個的原因是子查詢出來有字段相同,可以改字段方式解決
select *
from
(select si.name as siname,gsi.name as gsiname from student_infos si join good_student_infos gsi on si.name = gsi.name ) st;
如果不出現重復字段不會報錯
聯合查詢代替hive不能join非相等查詢問題