hive中join的on和where

昨天發現線上有一個job用了1w多個map,致使其餘job一直在等待mapred資源java


wKioL1L-J1eSz5PlAANGULZV--k268.jpg

爲了不影響別的job,暫時先殺掉,而後分析緣由。mysql

通常產生大量map有兩個緣由:sql

1.輸入的數據量比較大,致使根據split產生map時有大量的map產生ide

2.小文件比較多,同時沒有使用combine的inputformat,這樣在產生map時,每一個文件就會至少生成一個split。優化

由於默認使用了combine的inputformat,並設置了合適的合併條件,所以排除第二個緣由。spa

運行的sql:code

select  aa1.order_id,aa1.user_id,coalesce(b1.total,0) as total,
to_date(aa1.add_time) ord_dt,
b1.update_time,
datediff(to_date(aa1.add_time),to_date(b1.update_time)) mark
FROM
dddd.dd aa1
left outer join
dddd.cc b1
on
(aa1.user_id=b1.user_id and aa1.dt='20140212' and b1.dt='20140211');


經過explain extended分析sql:orm

發現aa1表並無根據aa1.dt='20140212'來過濾partition,而是對錶的文件進行了全局的掃描。blog

若是是inner join的話,能夠正常過濾,也就是在left join的狀況下,左邊的表不會根據on的條件來過濾數據,能夠經過在後面再增長where語句來實現過濾的功能。ip

分析二者的執行計劃區別:

1.left join + on

(TOK_QUERY (TOK_FROM (TOK_LEFTOUTERJOIN (TOK_TABREF (TOK_TABNAME vipdw dw_trd_order_cut) aa1) (TOK_TABREF (TOK_TABNAME vipdw dw_vip_vmark) b1) (and (and (= (. (TOK_TABLE_OR_COL aa1) user_id) (. (TOK_TABLE_OR_COL b1) user_id)) (= (. (TOK_TABLE_OR_COL aa1) dt) '20140212')) (= (. (TOK_TABLE_OR_COL b1) dt) '20140211')))) (TOK_INSERT (TOK_DESTINATION (TOK_DIR TOK_TMP_FILE)) (TOK_SELECT (TOK_SELEXPR (. (TOK_TABLE_OR_COL aa1) order_id)) (TOK_SELEXPR (. (TOK_TABLE_OR_COL aa1) user_id)) (TOK_SELEXPR (TOK_FUNCTION coalesce (. (TOK_TABLE_OR_COL b1) total) 0) total) (TOK_SELEXPR (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL aa1) add_time)) ord_dt) (TOK_SELEXPR (. (TOK_TABLE_OR_COL b1) update_time)) (TOK_SELEXPR (TOK_FUNCTION datediff (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL aa1) add_time)) (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL b1) update_time))) mark))))

2.left join + on + where

(TOK_QUERY (TOK_FROM (TOK_LEFTOUTERJOIN (TOK_TABREF (TOK_TABNAME vipdw dw_trd_order_cut) aa1) (TOK_TABREF (TOK_TABNAME vipdw dw_vip_vmark) b1) (and (and (= (. (TOK_TABLE_OR_COL aa1) user_id) (. (TOK_TABLE_OR_COL b1) user_id)) (= (. (TOK_TABLE_OR_COL aa1) dt) '20140212')) (= (. (TOK_TABLE_OR_COL b1) dt) '20140211')))) (TOK_INSERT (TOK_DESTINATION (TOK_DIR TOK_TMP_FILE)) (TOK_SELECT (TOK_SELEXPR (. (TOK_TABLE_OR_COL aa1) order_id)) (TOK_SELEXPR (. (TOK_TABLE_OR_COL aa1) user_id)) (TOK_SELEXPR (TOK_FUNCTION coalesce (. (TOK_TABLE_OR_COL b1) total) 0) total) (TOK_SELEXPR (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL aa1) add_time)) ord_dt) (TOK_SELEXPR (. (TOK_TABLE_OR_COL b1) update_time)) (TOK_SELEXPR (TOK_FUNCTION datediff (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL aa1) add_time)) (TOK_FUNCTION to_date (. (TOK_TABLE_OR_COL b1) update_time))) mark)) (TOK_WHERE (= (. (TOK_TABLE_OR_COL aa1) dt) '20140212'))))


能夠看到在增長where後增長了

(TOK_WHERE (= (. (TOK_TABLE_OR_COL aa1) dt) '20140212')) 的邏輯,優化器會先進行partition purge,而後再進行join操做。


其實在mysql中也是這種狀況:

inner join中的join key能夠做爲過濾條件。 left/right outer join類的join key不能做爲驅動表的過濾條件,要實現過濾的話能夠經過on + where組合。
相關文章
相關標籤/搜索