[譯]Hive學(xué)習(xí)指南(五)

動(dòng)態(tài)分區(qū)插入

前面的示例中,用戶(hù)必須知道對(duì)哪個(gè)分區(qū)插入數(shù)據(jù),并且一條insert語(yǔ)句只能插入一個(gè)分區(qū)。如果想要加載到多個(gè)分區(qū),需要使用多條insert語(yǔ)句,如下:

FROM page_view_stg pvs
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='US')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'US'
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='CA')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'CA'
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country='UK')
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip WHERE pvs.country = 'UK';

為了將數(shù)據(jù)加載到特定日期的所有國(guó)家分區(qū)中,需要為每個(gè)國(guó)家寫(xiě)insert語(yǔ)句。這樣很不方便,你得預(yù)先知道國(guó)家列表并且創(chuàng)建好分區(qū)。如果有一天國(guó)家列表改變了,你還得修改insert語(yǔ)句同時(shí)得創(chuàng)建對(duì)應(yīng)的分區(qū)。這樣做效率還低,每個(gè)insert語(yǔ)句都會(huì)變成MapReduce作業(yè)。

動(dòng)態(tài)分區(qū)插入(或者多分區(qū)插入)就是為解決上述問(wèn)題設(shè)計(jì)的,動(dòng)態(tài)分區(qū)插入會(huì)在掃描輸入表時(shí)動(dòng)態(tài)決定應(yīng)該創(chuàng)建和填充哪些分區(qū)。這是新加的特性,從0.6.0版本可用。使用動(dòng)態(tài)分區(qū)插入,會(huì)對(duì)輸入列的值進(jìn)行評(píng)估,然后決定每行數(shù)據(jù)應(yīng)該插入哪個(gè)分區(qū)。如果分區(qū)沒(méi)有創(chuàng)建,會(huì)自動(dòng)創(chuàng)建分區(qū)。使用這個(gè)特性只需要寫(xiě)一條insert語(yǔ)句。另外,因?yàn)橹挥幸粭linsert語(yǔ)句,也只有一個(gè)對(duì)應(yīng)的MapReduce作業(yè)。相比多條inser的情況,這個(gè)特性會(huì)顯著提升性能,減少Hadoop集群的工作負(fù)載。

下面是一個(gè)加載所有國(guó)家分區(qū)數(shù)據(jù)的示例,只用到一條insert語(yǔ)句:

FROM page_view_stg pvs
INSERT OVERWRITE TABLE page_view PARTITION(dt='2008-06-08', country)
       SELECT pvs.viewTime, pvs.userid, pvs.page_url, pvs.referrer_url, null, null, pvs.ip, pvs.country

動(dòng)態(tài)分區(qū)插入和多條insert語(yǔ)句有一些語(yǔ)法差異:

  • PARTITION中添加了country,但是沒(méi)有相關(guān)值。在這種情況下,country就是動(dòng)態(tài)分區(qū)列。dt有值,它是靜態(tài)分區(qū)列。如果是動(dòng)態(tài)分區(qū)列,它的值將會(huì)來(lái)自輸入列。目前只允許動(dòng)態(tài)分區(qū)列是最后一列,因?yàn)榉謪^(qū)列的順序說(shuō)明了其層次順序(意味著dt是root分區(qū),country是child分區(qū)),不能寫(xiě)成(dt, country='US')。
  • select語(yǔ)句中添加了pvs.country列。這是動(dòng)態(tài)分區(qū)列對(duì)應(yīng)的輸入列。注意,不需要給靜態(tài)分區(qū)列添加輸入列,因?yàn)?code>PARTITION語(yǔ)句知道它的值。動(dòng)態(tài)分區(qū)值是按照順序查詢(xún)的,不是按照名稱(chēng),并且是select語(yǔ)句的最后一列。

自定義Map/Reduce腳本

用戶(hù)可以加入已定義的Map/Reduce,這個(gè)特性是Hive語(yǔ)言原生支持的。例如,想要運(yùn)行自動(dòng)的腳本map_script和reduce_script,用戶(hù)可以執(zhí)行以下命令,使用TRANSFORM語(yǔ)句嵌入腳本。

注意,在傳給腳本之前,列會(huì)被轉(zhuǎn)換為字符串并以TAB分隔,用戶(hù)腳本的標(biāo)準(zhǔn)輸出會(huì)被當(dāng)做以TAB分隔的字符串列。用戶(hù)腳本的標(biāo)準(zhǔn)錯(cuò)誤可以在Hadoop的任務(wù)詳情頁(yè)面看到。

FROM (
     FROM pv_users
     MAP pv_users.userid, pv_users.date
     USING 'map_script'
     AS dt, uid
     CLUSTER BY dt) map_output
 
 INSERT OVERWRITE TABLE pv_users_reduced
     REDUCE map_output.dt, map_output.uid
     USING 'reduce_script'
     AS date, count;

示例map腳本(weekday_mapper.py)

import sys
import datetime
 
for line in sys.stdin:
  line = line.strip()
  userid, unixtime = line.split('\t')
  weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
  print ','.join([userid, str(weekday)])

當(dāng)然,MAP和REDUCE都是語(yǔ)法糖。內(nèi)部查詢(xún)可以寫(xiě)為:

SELECT TRANSFORM(pv_users.userid, pv_users.date) USING 'map_script' AS dt, uid CLUSTER BY dt FROM pv_users;

無(wú)模式map/reduce:如果"USING map_script"后沒(méi)有"AS"語(yǔ)句,Hive假定腳本的輸出包含2個(gè)部分:key,放在tab之前,value,除key之外其余都放在tab之后。這和指定了"AS key, value"是有區(qū)別的,因?yàn)槿绻卸鄠€(gè)tab的話(huà),value只會(huì)包含了第一個(gè)tab和第二個(gè)tab之間的部分。

用這種方式,用戶(hù)可以在不知道m(xù)ap輸出模式的情況下遷移老的map/reduce腳本。不過(guò)用戶(hù)還是需要知道reduce輸出模式,因?yàn)楸仨毰c我們要插入的表進(jìn)行匹配。通常分區(qū)列是排序列的前綴,但并不強(qiáng)制。

FROM (
    FROM pv_users
    MAP pv_users.userid, pv_users.date
    USING 'map_script'
    CLUSTER BY key) map_output
 
INSERT OVERWRITE TABLE pv_users_reduced
 
    REDUCE map_output.dt, map_output.uid
    USING 'reduce_script'
    AS date, count;

DISTRIBUTE BY和SORT BY:不指定"cluster by",用戶(hù)可以指定"distribute by"和"sort by",分區(qū)列和排序列可以不同。

    FROM pv_users
    MAP pv_users.userid, pv_users.date
    USING 'map_script'
    AS c1, c2, c3
    DISTRIBUTE BY c2
    SORT BY c2, c1) map_output
 
INSERT OVERWRITE TABLE pv_users_reduced
 
    REDUCE map_output.c1, map_output.c2, map_output.c3
    USING 'reduce_script'
    AS date, count;

Co-Groups

假設(shè)我們要用uid列組合actions_video和action_comments表的行,并且將數(shù)據(jù)發(fā)送到自定義的'reduce_script',可以使用如下方式:

FROM (
     FROM (
             FROM action_video av
             SELECT av.uid AS uid, av.id AS id, av.date AS date
 
            UNION ALL
 
             FROM action_comment ac
             SELECT ac.uid AS uid, ac.id AS id, ac.date AS date
     ) union_actions
     SELECT union_actions.uid, union_actions.id, union_actions.date
     CLUSTER BY union_actions.uid) map
 
 INSERT OVERWRITE TABLE actions_reduced
     SELECT TRANSFORM(map.uid, map.id, map.date) USING 'reduce_script' AS (uid, id, reduced_val);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容