Hive(五)hive的高級應用


一、視圖

視圖:享用基本表的數據,不會生成另外一份數據
創建視圖:
create view view_name as select * from carss;
create view carss_view as select * from carss limit 500;
查看視圖:
desc view_name
desc carss_view
刪除視圖:
drop view view_name
drop view carss_view
使用視圖:
create view sogou_view as select * from sogou_table where rank > 3 ;
select count(distinct uid) from sogou_view;

二、hive特殊分隔符處理

補充: hive 讀取數據的機制:
(1) 首先用 InputFormat<默認是: org.apache.hadoop.mapred.TextInputFormat >的一個具體實 現類讀入文件數據,返回一條一條的記錄(可以是行,或者是你邏輯中的“行”)
(2) 然后利用 SerDe<默認: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe>的一個具體 實現類,對上面返回的一條一條的記錄進行字段切割
Hive 對文件中字段的分隔符默認情況下只支持單字節分隔符,如果數據文件中的分隔符是多字符的,如下所示:
01||huangbo
02||xuzheng
03||wangbaoqiang
可用以下方式處理:

1、使用 RegexSerDe 通過正則表達式來抽取字段

create table t_bi_reg(id string,name string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties('input.regex'='(.*)\\|\\|(.*)','output.format.string'='%1$s %2$s')               如果三個字段,再加上一個%3$s
stored as textfile;


hive>load data local inpath '/root/hivedata/bi.dat' into table t_bi_reg;
hive>select * from t_bi_reg;

2、通過自定義 InputFormat 解決特殊分隔符問題

其原理是在 inputformat 讀取行的時候將數據中的“多字節分隔符”替換為 hive 默認的 分隔符( ctrl+A 亦即 \001)或用於替代的單字符分隔符,以便 hive 在 serde 操作時按照 默認的單字節分隔符進行字段抽取

修改com.ghgj.hive.delimit2. BiDelimiterInp
      com.ghgj.hive.delimit2. BiRecordReader

把自定義的類(修改的源代碼)打包    上傳包 在mv xx.jar apps/apa...../lib/       重啟hive , 建表時引用自己定義的類  (復雜查詢時還要 add jar 包)

三、數據傾斜

   1、什么是數據傾斜

     由於數據分布不均勻,造成數據大量的集中到一點,造成數據熱點。

   2、 Hadoop 框架的特性

   A、 不怕數據大,怕數據傾斜。
   B、 Jobs 數比較多的作業運行效率相對比較低,如子查詢比較多。
   C、 sum,count,max,min 等聚集函數,不會有數據傾斜問題  

  3、 容易數據傾斜情況
   A、 group by 不和聚集函數搭配使用的時候。
   B、 count(distinct ),在數據量大的情況下,容易數據傾斜,因為 count(distinct)是按 group by 字段分組,按 distinct 字段排序。
   C、 小表關聯超大表

4、 產生數據傾斜的原因:
A: key 分布不均勻
B:業務數據本身的特性
C:建表考慮不周全
D:某些 HQL 語句本身就存在數據傾斜

5、 主要表現:
任務進度長時間維持在 99%或者 100%的附近, 查看任務監控頁面,發現只有少量 reduce子任務未完成, 因為其處理的數據量和其他的 reduce 差異過大。
單一 reduce 處理的記錄數和平均記錄數相差太大,通常達到好幾倍之多,最長時間遠大 於平均時長。(耗時長)

6、業務場景

A: 空值產生的數據傾斜
場景說明: 在日志中,常會有信息丟失的問題, 比如日志中的 user_id,如果取其中的 user_id 和用戶表中的 user_id 相關聯,就會碰到數據傾斜的問題。

解決方案 1: user_id 為空的不參與關聯
select * from log a join user b on a.user_id is not null and a.user_id = b.user_id union all
select * from log c where c.user_id is null;
解決方案 2: 賦予空值新的 key 值
select * from log a left outer join user b on case when a.user_id is null then
concat(‘hive’,rand()) else a.user_id end = b.user_id
總結: 方法 2 比方法 1 效率更好, 不但 IO 少了,而且作業數也少了,方案 1 中, log 表 讀了兩次, jobs 肯定是 2,而方案 2 是 1。 這個優化適合無效 id(比如-99, ’’, null)產 生的數據傾斜, 把空值的 key 變成一個字符串加上一個隨機數,就能把造成數據傾斜的 數據分到不同的 reduce 上解決數據傾斜的問題。

B:不同數據類型關聯產生數據傾斜
場景說明: 用戶表中 user_id 字段為 int, log 表中 user_id 為既有 string 也有 int 的類型, 當按照兩個表的 user_id 進行 join 操作的時候,默認的 hash 操作會按照 int 類型的 id 進 行分配,這樣就會導致所有的 string 類型的 id 就被分到同一個 reducer 當中
解決方案: 把數字類型 id 轉換成 string 類型的 id
select * from user a left outer join log b on b.user_id = cast(a.user_id as string)

 



 

 





 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM