hive 的分隔符、orderby sort by distribute by的优化
一、Hive 分號字符
分號是SQL語句結束標記,在HiveQL中也是,可是在HiveQL中,對分號的識別沒有那么智慧,比如:
select concat(cookie_id,concat(';',’zoo’)) fromc02_clickstat_fatdt1 limit 2;
FAILED: Parse Error: line 0:-1 cannot recognize input'<EOF>' in function specification
能夠判斷,Hive解析語句的時候,僅僅要遇到分號就覺得語句結束,而不管是否用引號包括起來。
解決的辦法是,使用分號的八進制的ASCII碼進行轉義,那么上述語句應寫成:
select concat(cookie_id,concat('\073','zoo')) fromc02_clickstat_fatdt1 limit 2;
為什么是八進制ASCII碼?
我嘗試用十六進制的ASCII碼,但Hive會將其視為字符串處理并未轉義,好像僅支持八進制,原因不詳。這個規則也適用于其它非SELECT語句,如CREATE TABLE中須要定義分隔符,那么對不可見字符做分隔符就須要用八進制的ASCII碼來轉義。
二、insert 新增數據
依據語法Insert必須加“OVERWRITE”keyword,也就是說每一次插入都是一次重寫。那怎樣實現表中新增數據呢?
如果Hive中有表manbu,
hive> DESCRIBE manbu;
id int
value int
hive> SELECT * FROM manbu;
3 4
1 2
2 3
現添加一條記錄:
hive> INSERT OVERWRITE TABLE manbu
SELECT id, value FROM (
SELECT id, value FROM manbu
UNION ALL
SELECT 4 AS id, 5 AS value FROM manbu limit 1
) u;
結果是:
hive>SELECT * FROM p1;
3 4
4 5
2 3
1 2
當中的關鍵在于, keywordUNION ALL的應用, 即將原有數據集和新增數據集進行結合, 然后重寫表.
三、初始值
INSERT OVERWRITE TABLE在插入數據時, 后面的字段的初始值應注意與表定義中的一致性. 比如, 當為一個STRING類型字段初始為NULL時:
NULL AS field_name // 這可能會被提示定義類型為STRING, 但這里是void
CAST(NULL AS STRING) AS field_name // 這樣是正確的
又如, 為一個BIGINT類型的字段初始為0時:
CAST(0 AS BIGINT) AS field_name
四、orderby? sort by ?distribute by的優化
Hive的排序keyword是SORT BY,它有意差別于傳統數據庫的ORDER BY也是為了強調兩者的差別–SORT BY僅僅能在單機范圍內排序。
比如:
?set mapred.reduce.tasks=2;(設置reduce的數量為2 )
原值:
1.selectcookie_id,page_id,id from c02_clickstat_fatdt1
where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')
1.193.148.164.1288609861509.2??113181412886099008861288609901078194082403????? 684000005
1.193.148.164.1288609861509.2??127001128860563972141288609859828580660473????? 684000015
1.193.148.164.1288609861509.2?? 113181412886099165721288609915890452725326????? 684000018
1.193.131.218.1288611279693.0??01c183da6e4bc50712881288611540109914561053????? 684000114
1.193.131.218.1288611279693.0??01c183da6e4bc22412881288611414343558274174????? 684000118
1.193.131.218.1288611279693.0??01c183da6e4bc50712881288611511781996667988????? 684000121
1.193.131.218.1288611279693.0??01c183da6e4bc22412881288611523640691739999????? 684000126
1.193.131.218.1288611279693.0??01c183da6e4bc50712881288611540109914561053????? 684000128?
2. selectcookie_id,page_id,id from c02_clickstat_fatdt1 where
cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')
SORT BYCOOKIE_ID,PAGE_ID;
SORT排序后的值
1.193.131.218.1288611279693.0?????????? 684000118?????? 01c183da6e4bc22412881288611414343558274174????? 684000118
1.193.131.218.1288611279693.0?????????? 684000114??????01c183da6e4bc50712881288611540109914561053????? 684000114
1.193.131.218.1288611279693.0?????????? 684000128??????01c183da6e4bc50712881288611540109914561053????? 684000128
1.193.148.164.1288609861509.2?????????? 684000005??????113181412886099008861288609901078194082403????? 684000005
1.193.148.164.1288609861509.2?????????? 684000018??????113181412886099165721288609915890452725326????? 684000018
1.193.131.218.1288611279693.0?????????? 684000126??????01c183da6e4bc22412881288611523640691739999????? 684000126
1.193.131.218.1288611279693.0?????????? 684000121??????01c183da6e4bc50712881288611511781996667988????? 684000121
1.193.148.164.1288609861509.2?????????? 684000015? ?????127001128860563972141288609859828580660473????? 684000015
selectcookie_id,page_id,id from c02_clickstat_fatdt1
where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')
ORDER BYPAGE_ID,COOKIE_ID;
1.193.131.218.1288611279693.0?????????? 684000118??????01c183da6e4bc22412881288611414343558274174????? 684000118
1.193.131.218.1288611279693.0?????????? 684000126??????01c183da6e4bc22412881288611523640691739999????? 684000126
1.193.131.218.1288611279693.0?????????? 684000121?? ????01c183da6e4bc50712881288611511781996667988????? 684000121
1.193.131.218.1288611279693.0?????????? 684000114??????01c183da6e4bc50712881288611540109914561053????? 684000114
1.193.131.218.1288611279693.0?????????? 684000128?????? 01c183da6e4bc50712881288611540109914561053????? 684000128
1.193.148.164.1288609861509.2?????????? 684000005??????113181412886099008861288609901078194082403????? 684000005
1.193.148.164.1288609861509.2?????????? 684000018??????113181412886099165721288609915890452725326????? 684000018
1.193.148.164.1288609861509.2?????????? 684000015??????127001128860563972141288609859828580660473????? 684000015
能夠看到SORT和ORDER排序出來的值不一樣。一開始我指定了2個reduce進行數據分發(各自進行排序)。結果不一樣的主要原因是上述查詢沒有reduce key,hive會生成隨機數作為reduce key。這種話輸入記錄也隨機地被分發到不同reducer機器上去了。為了保證reducer之間沒有反復的cookie_id記錄,能夠使用DISTRIBUTE BYkeyword指定分發key為cookie_id。
selectcookie_id,country,id,page_id,id from c02_clickstat_fatdt1 where cookie_idIN('1.193.131.218.1288611279693.0','1.193.148.164.1288609861509.2')? distribute by cookie_id SORT BY COOKIE_ID,page_id;
1.193.131.218.1288611279693.0?????????? 684000118??????01c183da6e4bc22412881288611414343558274174????? 684000118
1.193.131.218.1288611279693.0?????????? 684000126??????01c183da6e4bc22412881288611523640691739999????? 684000126
1.193.131.218.1288611279693.0?????????? 684000121??????01c183da6e4bc50712881288611511781996667988????? 684000121
1.193.131.218.1288611279693.0?????????? 684000114??????01c183da6e4bc50712881288611540109914561053????? 684000114
1.193.131.218.1288611279693.0?????????? 684000128??????01c183da6e4bc50712881288611540109914561053????? 684000128
1.193.148.164.1288609861509.2?????????? 684000005??????113181412886099008861288609901078194082403????? 684000005
1.193.148.164.1288609861509.2?????????? 684000018?????? 113181412886099165721288609915890452725326????? 684000018
1.193.148.164.1288609861509.2?????????? 684000015??????127001128860563972141288609859828580660473????? 684000015
例二:
CREATETABLE if not exists t_order(
id int,-- 編號
sale_idint, -- SID
customer_idint, -- CID
product_id int, -- PID
amountint -- 數量
)PARTITIONED BY (ds STRING);
在表中查詢全部記錄,并依照PID和數量排序:
setmapred.reduce.tasks=2;
Selectsale_id, amount from t_order
Sort bysale_id, amount;
這一查詢可能得到非期望的排序。指定的2個reducer分發到的數據可能是(各自排序):
Reducer1:
Sale_id |amount
0 | 100
1 | 30
1 | 50
2 | 20
Reducer2:
Sale_id |amount
0?|110
0 | 120
3 | 50
4 | 20
使用DISTRIBUTE BYkeyword指定分發key為sale_id。改造后的HQL例如以下:
setmapred.reduce.tasks=2;
Selectsale_id, amount from t_order
Distributeby sale_id
Sort bysale_id, amount;
這樣可以保證查詢的銷售記錄集合中,銷售ID相應的數量是正確排序的,可是銷售ID不能正確排序,原因是hive使用hadoop默認的HashPartitioner分發數據。
這就涉及到一個全排序的問題。解決的辦法無外乎兩種:
1.) 不分發數據,使用單個reducer:
setmapred.reduce.tasks=1;
這一方法的缺陷在于reduce端成為了性能瓶頸,并且在數據量大的情況下一般都無法得到結果。可是實踐中這仍然是最經常使用的方法,原因是通常排序的查詢是為了得到排名靠前的若干結果,因此能夠用limit子句大大降低數據量。使用limit n后,傳輸到reduce端(單機)的數據記錄數就降低到n* (map個數)。
2.) 改動Partitioner,這樣的方法能夠做到全排序。這里能夠使用Hadoop自帶的TotalOrderPartitioner(來自于Yahoo!的TeraSort項目),這是一個為了支持跨reducer分發有序數據開發的Partitioner,它須要一個SequenceFile格式的文件指定分發的數據區間。假設我們已經生成了這一文件(存儲在/tmp/range_key_list,分成100個reducer),能夠將上述查詢改寫為
setmapred.reduce.tasks=100;
sethive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderPartitioner;
settotal.order.partitioner.path=/tmp/ range_key_list;
Selectsale_id, amount from t_order
Clusterby sale_id
Sort byamount;
有非常多種方法生成這一區間文件(比如hadoop自帶的o.a.h.mapreduce.lib.partition.InputSampler工具)。這里介紹用Hive生成的方法,比如有一個按id有序的t_sale表:
CREATETABLE if not exists t_sale (
id int,
namestring,
locstring
);
則生成按sale_id分發的區間文件的方法是:
createexternal table range_keys(sale_id int)
rowformat serde
'org.apache.hadoop.hive.serde2.binarysortable.BinarySortableSerDe'
stored as
inputformat
'org.apache.hadoop.mapred.TextInputFormat'
outputformat
'org.apache.hadoop.hive.ql.io.HiveNullValueSequenceFileOutputFormat'
location'/tmp/range_key_list';?
insertoverwrite table range_keys
selectdistinct sale_id
fromsource t_sale sampletable(BUCKET 100 OUT OF 100 ON rand()) s
sort bysale_id;
生成的文件(/tmp/range_key_list文件夾下)能夠讓TotalOrderPartitioner按sale_id有序地分發reduce處理的數據。
區間文件須要考慮的主要問題是數據分發的均衡性,這有賴于對數據深入的理解。
轉載于:https://www.cnblogs.com/mfrbuaa/p/4211029.html
總結
以上是生活随笔為你收集整理的hive 的分隔符、orderby sort by distribute by的优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: unity值得推荐的网址
- 下一篇: 好网站