問(wèn)題表述
最近業(yè)務(wù)線故障,一些用戶(hù)受到了影響。產(chǎn)品經(jīng)理急切需要知道,這次事故是否導(dǎo)致用戶(hù)流失,換句話希望看看這些用戶(hù)近一個(gè)星期的購(gòu)物留存。所以產(chǎn)品經(jīng)理給數(shù)據(jù)工程師提供了一個(gè)大概有1.4萬(wàn)的受影響用戶(hù)id的文本文件accidentIds.txt,希望通過(guò)購(gòu)買(mǎi)記錄表(order_table)知道從事故發(fā)生當(dāng)天開(kāi)始,7天內(nèi)這部分人群的再次消費(fèi)人數(shù)和消費(fèi)金額。數(shù)據(jù)按天給出。
- accidentIds.txt數(shù)據(jù)形式。
123
234
345
- order_table表結(jié)構(gòu)
| create_time | user_id | purchase |
|---|---|---|
| 2017-07-10 10:20:29 | 123 | 90 |
| 2017-07-10 23:23:23 | 123 | 30 |
| 2017-07-11 13:23:23 | 345 | 60 |
| 2017-07-12 03:23:23 | 234 | 130 |
分析
用戶(hù)購(gòu)買(mǎi)記錄屬于業(yè)務(wù)表,通常會(huì)從mysql抽到hive當(dāng)中來(lái)進(jìn)行統(tǒng)計(jì)計(jì)算。而需求方提供的卻是一個(gè)文本文件,完成這個(gè)需求,其實(shí)最笨的一個(gè)做法都是在hive里建一個(gè)臨時(shí)表,然后把文件load進(jìn)去,連表查詢(xún)就行了。但是這樣做,真的很麻煩,出數(shù)據(jù)的效率也不高。
這時(shí)我們應(yīng)該想起Linux的一個(gè)高效工具——awk。
如果我們是從hive中把按天、用戶(hù)id、夠買(mǎi)金額總和的形式把數(shù)據(jù)導(dǎo)出到服務(wù)器,然后再awk計(jì)算,就會(huì)方便會(huì)多,出數(shù)據(jù)簡(jiǎn)直是秒級(jí)別。
具體步驟
假設(shè)當(dāng)前工作目錄,既是最后輸出目錄。且已經(jīng)把a(bǔ)ccidentIds.txt拷貝到當(dāng)前目錄。接下來(lái):
- 把數(shù)據(jù)導(dǎo)出到buylist.txt
hive -e "
use database_a;
select substr(create_time,1,10) as dt,user_id,sum(purchase)
from order_table
group by substr(create_time,1,10),user_id
">buylist.txt
- awk處理
awk 'NR==FNR{
//把a(bǔ)ccidentIds.txt的id存到uidDict數(shù)組中,且下標(biāo)用id標(biāo)識(shí)
uidDict[$1]=$1; }
NR>FNR{
//對(duì)于buylist.txt中的記錄,$2表示user_id只要在uidDict中出現(xiàn),表示有夠買(mǎi)
if(uidDict[$2]!=""){
//$1是夠買(mǎi)日期
day[$1]=$1;
//userCount是按日期計(jì)數(shù)數(shù)組,表示夠買(mǎi)過(guò)的人數(shù)
userCount[$1]++;
//$3表示某個(gè)人某天的夠買(mǎi)金額總和,purchase是按日期累加夠買(mǎi)金額
purchase[$1]=purchase[$1]+$3;}}
END{
//按天輸出
for (i in day) {
print day[i],userCount[i],purchase[i]
}}' accidentIds.txt buylist.txt
輸出
2017-07-10 123 120
2017-07-11 345 60
2017-07-12 234 130
結(jié)語(yǔ)
對(duì)于1.4萬(wàn)條數(shù)據(jù)的accidentIds.txt和38萬(wàn)條數(shù)據(jù)的buylist.txt,awk命令的計(jì)算結(jié)果簡(jiǎn)直是秒出。
而用hive連表,首先導(dǎo)表,再連表查詢(xún),怎么著也得折騰個(gè)半個(gè)小時(shí)。
所以用好awk真心省時(shí)省力?。。?!