天天看點

hive的進一步了解HIVE的基本了解,使用,特性HIVE動态分區HIVE鎖表問題HIVE資料傾斜hql性能調優hive 小表與大表關聯執行MR或聚集查詢卡死

目錄

HIVE的基本了解,使用,特性

什麼是hive

hive中繼資料

hive預設分隔符   \001

hive行級更新操作的前提條件

hive/mysql/hbase比較

函數

hive解決wordcount案例

hive内部表與外部表

hql特性:

hive常用指令:

讀取資料檔案方法:

檢視yarn mr日志

HIVE動态分區

HIVE鎖表問題

HIVE資料傾斜

hql性能調優

hive 小表與大表關聯

執行MR或聚集查詢卡死

HIVE的基本了解,使用,特性

什麼是hive

hive------mapreduce的封裝,意義在于将sql語言轉化為mapreduce的過程,本質是個mapreduce,批處理強大,不支援單條紀錄級别的update操作,随機讀寫性能差    (hive是個計算架構,不能存儲資料)

hbase-----hdfs的包裝,本質是資料存儲,克服hdfs在随機讀寫上的缺點

kudu-----不及HDFS批處理快,也不及HBase随機讀寫能力強,但是反過來它比HBase批處理快(适用于OLAP的分析場景),而且比HDFS随機讀寫能力強,适用于實時寫入或者更新的場景。

hive的表本質就是hadoop的目錄/檔案(檔案夾),hive依托hdfs存儲,依托yarn資源排程,依托mapreduce進行計算

hive中繼資料

hive中繼資料預設存儲在derby中,也可存儲與mysql中,中繼資料是指表的資訊,比如表的名字,表有哪些列等等描述資訊。我們向表中插入的資料是儲存在HDFS上的。

hive預設分隔符   \001

hive行級更新操作的前提條件

1 注意存儲格式按ORC方式

2 進行資料分桶

3 添加表屬性:"transactional"="true"   該設定不可逆,使得該表

4.hive-site.xml裡要做相關配置  參見 https://blog.csdn.net/wzy0623/article/details/51483674

hive/mysql/hbase比較

hive mysql hbase
資料量
速度 資料量大時快 資料量小時快
查詢 增删改 增删改

函數

系統函數: 月: date_format     last_day                   周:    next_day                                            日:date_add date_sub                解析json: get_json_object

rank() over()                            1,1,3,4,5,6,7              跳躍排序

row_number() over()               1,2,3,4,5,6,7

dense_rank() over()                1,1,2,3,4,5,6               連續排序(最大排名會小于總數)

hive解決wordcount案例

select word,count(*) from (
select explode(split(sentence.' ')) word from article
) t 
group by word 
           

hive内部表與外部表

create table                   create external table

内部表               vs            外部表

表結構和資料均丢失             表結構丢失,但資料仍在           

不可挽回                       把表重建,資料自動恢複

hql特性:

1.0.13版本前的hive僅支援from 後面的子查詢,0.13版本後的hive新增支援 in(not in)後面的子查詢/ EXISTS(NOT EXISTS)後面的子查詢

2. 子查詢相當于表名,必須有别名。

3. hive 不支援union ,隻支援union all 

4. 子查詢中使用union all 時,在子查詢裡不能使用count、sum 等 聚合函數 

5. 兩表直接進行union all 可以使用count、sum 等聚合函數 

6. 兩張表進行union all 取相同的字段名稱,可正常輸出指定資料内容,且結果為兩張表的結果集

hive常用指令:

普通建立:

-- 建立表,external 外部表
CREATE external TABLE IF NOT EXISTS t2(id int,name string,age int)
COMMENT 'xx' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE ; 
-- 加載資料到hive表
load data local inpath '/home/centos/customers.txt' into table t2 ;	-- local上傳檔案
load data inpath '/user/centos/customers.txt' [overwrite] into table t2 ;	-- 移動檔案
-- 加載資料到分區表
load data local inpath '/home/centos/customers.txt' into table t3 partition(year=2014,month=11);
-- 啟用/禁用表
ALTER TABLE t2 ENABLE NO_DROP;	-- 不允許删除
ALTER TABLE t2 DISABLE NO_DROP;	-- 允許删除
-- 複制表
create table tt as select * from users ;		-- 攜帶資料和表結構
create table tt like users ;			-- 不帶資料,隻有表結構
           

分區表:

-- 建立分區表.
create table t3(id int,name string,age int) partition by (year int,month int) row farmat delimited fields terminated by ','  stored as textfile;
-- 顯式表的分區資訊
show partitions t3;
-- 添加分區,建立目錄
alter table add partition (year = 2021,month = 03)
-- 删除分區
alter table t3 drop if exists partition (year = 2021,month = 03)
-- 分區結構
/user/hive/warehouse/mydb2.db/t3/year=2014/month=11
/user/hive/warehouse/mydb2.db/t3/year=2014/month=12
-- 加載資料到分區表
load data [local] inpath '/home/centos/customers.txt' [overwrite] into table t3 [partition (year 2021,month 03)]
           

分桶表:

-- 建立桶表t4
create table t4 (id int,name string,age int) clusted by (id) into 3 buckets row farmat delimited fields terminated by ','  stored as textfile;
-- 加載資料不會進行分桶操作
load data [local] inpath '/home/centos/customers.txt' into table t4;
-- 查詢t3表資料插入到t4中。
insert into t4 select id,name,age from t3;
           

桶表的數量如何設定?

評估資料量,保證每個桶的資料量block的2倍大小。(從2.7.3版本開始,官方關于Data Blocks 的說明中,block size由64 MB變成了128 MB的。)

既分區又分桶:

create table t_test (id int)
partitioned by (type string)
clustered by (id) into 3 buckets
row format delimited fields terminated by '\t';
-- partition by 要寫在clustered by 前面
           

hive删除資料: 

hive删除資料不支援單條紀錄級别

--------------------------------------- 分區表
----------------删除具體partition 
alter table t4 drop if exists partition (year = 2021,month = 02);
----------------删除partition内部分資料
insert overwrite into table t4 partition (year = 2021,month = 02)
select * from t4 where year = 2021 and month = 02 and age<20;


--------------------------------------- 非分區表
INSERT OVERWRITE TABLE t4 SELECT * FROM t4 WHERE age is not null;
           

讀取資料檔案方法:

TextFile , SequenceFile(二進制) , RCFile

SequenceFile(二進制): 是hadoop提供的一種二進制檔案,<key,value>形式序列化到檔案中.java Writable接口進行序列化和反序列化

RCFile: 是hive專門推出的面向列的資料格式

檢視yarn mr日志

檢視application的日志:

[[email protected] ~]$ yarn logs -applicationId application_1523430872525_0002 

檢視具體某一個container的日志:

[[email protected] ~]$ yarn logs -applicationId application_1523430872525_0002 -containerId container_1523191604137_0016_02_000001 -nodeAddress hadoop01:60127
           

HIVE動态分區

hive單字段動态分區:(預設最後一個字段對應分區字段)

hive>
   create table dpartition(id int ,name string )
   partitioned by(ct string  );
hive>
 hive.exec.dynamici.partition=true;  #開啟動态分區,預設是false
 set hive.exec.dynamic.partition.mode=nonstrict; #開啟允許所有分區都是動态的,否則必須要有靜态分區才能使用。
 insert overwrite table dpartition
 partition(ct)
 select id ,name,city from  mytest_tmp2_p; 
 
要點:因為dpartition表中隻有兩個字段,是以當我們查詢了三個字段時(多了city字段),是以系統預設以最後一個字段city為分區名,因為分區表的分區字段預設也是該表中的字段,且依次排在表中字段的最後面。
hive>--檢視可知,hive已經完成了以city字段為分區字段,實作了動态分區。
hive (fdm_sor)> show partitions dpartition;
partition
ct=beijing
ct=beijing1
           

hive多字段半自動分區:(靜态分區要放在動态分區前面,分區字段順序和partition 字段順序一緻)

1.建立一個隻有一個字段,兩個分區字段的分區表
hive (fdm_sor)> create table ds_parttion(id int ) 
              > partitioned by (state string ,ct string );
2.往該分區表半動态分區插入資料 
hive>
 set hive.exec.dynamici.partition=true;
 set hive.exec.dynamic.partition.mode=nonstrict;
 insert overwrite table ds_parttion
 partition(state='china',ct)  #state分區為靜态,ct為動态分區,以查詢的city字段為分區名
 select id ,city from  mytest_tmp2_p; 
 
           

hive多字段全部動态分區:(注意順序)

set hive.exec.dynamici.partition=true;
 set hive.exec.dynamic.partition.mode=nonstrict;
 insert overwrite table ds_parttion
 partition(state,ct)
 select id ,country,city from  mytest_tmp2_p; 
注意:字段的個數和順序不能弄錯。
           

動态參數必備參數:

  • hive.exec.dynamic.partition                             開啟動态分區,預設不開
  • hive.exec.dynamic.partition.mode                  動态分區的模式:預設strict,要求必須要有個靜态分區字段;一般需設定為nonstrict表示所有分區字段可使用動态分區
  • hive.exec.max.dynamic.partitions.pernode   每個執行MR的節點上最大能建立的分區數(比如一年365天,分區數要設定>365)
  • hive.exec.max.dynamic.partitions                  所有MR節點上最大能建立的分區數
  • hive.exec.max.created.files                             整個MR JOB中最大能建立的hdfs檔案數

Hive的靜态分區,實際上就是手動指定分區的值為靜态值,适用于小批量資料

HIVE鎖表問題

hive有兩種鎖,一種是 共享鎖(SHARED),查詢時會有。SHARED(共享鎖 S)和 Exclusive(排他鎖 X)。隻有都是共享鎖才不會鎖表/分區。

解決方法:

1.先檢視有沒有鎖。表級檢視和分區級檢視。

//   1 查詢是否鎖表:
 hive> show locks ;
//   2 發現表:test 被鎖
//   3 臨時解決辦法
hive> unlock table test;   //親測這個指令基本沒啥用,表依然處于無法操作狀态,但是可以試試
hive> unlock table test partition(dt='2019-05-05'); //解鎖分區鎖指令可以用這個
 


SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;
           

2.調整sql語句或者插入資料操作之間設定sleep或者設定相關關于hive鎖沖突時重新等待鎖釋放的參數

3.關閉鎖機制,set hive.support.concurrency=false

4.表建立分區,這樣鎖就會到分區級别,就會降低鎖表粒度。動态分區如非必要就關閉動态分區,因為動态分區的話,鎖級别就到表,不到分區。 set hive.exec.dynamic.partition=false

5.關閉事務:set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager

HIVE資料傾斜

闡述資料傾斜的原因:

資料分布不均勻;不同資料類型進行關聯操作(隻會有一個reduce);空數值易造成

解決資料傾斜的方法:

1.mapjoin     在map端做join操作減少資料,減少到reduce端彙總的資料

2.如果是不同資料類型關聯造成的就在sql中轉成一緻的資料類型再關聯

3. group by操作

4.開啟資料傾斜時的負載均衡  set hive.groupby.skewindata=true   

就是到reduce那後對于大的reduce再進行reduce       2個MRJOB

5.控制空值分布         将為空的key轉變為字元串加純随機數,将因空值而造成傾斜的資料分布到多個reducer  (本質和開啟資料傾斜時的負載均衡是一樣的)

hql性能調優

 1. mapjoin預設打開

set hive.auto.convert.join = true;  --是否開自動mapjoin

set hive.mapjoin.smalltable.filesize;   --mapjoin的表size大小

以上兩個參數同時使用,在hive.auto.convert.join為true時,隻要小表size小于hive.mapjoin.smalltable.filesize的設定值,并且小表不是關聯操作的最後一張表,小表就會走mapjoin。

MAPJION會把小表全部讀入記憶體中,在map階段直接拿另外一個表的資料和記憶體中表資料做比對,由于在map是進行了join操作,省去了reduce運作的效率也會高很多。

set hive.auto.convert.join = true;
 
set hive.mapjoin.smalltable.filesize = 6250000;
 
select * from table_1 --小表,size  5m
 
join table_2
 
on 1=1;
           

mapjoin還有一個很大的好處是能夠進行不等連接配接的join操作,如果将不等條件寫在where中,那麼mapreduce過程中會進行笛卡爾積,運作效率特别低,如果使用mapjoin操作,在map的過程中就完成了不等值的join操作,效率會高很多。

mapjoin适用的場景:   關聯操作中有一張表非常小;不等值的連結操作

2.行列過濾,就是在join操作前先進行where操作,減少資料集

3.做好分區。(分桶用于采樣)

4.小檔案

    CombineHiveInputformat      減少切片,進而減少Maptask,減少記憶體

    開啟JVM重用(減少開關時間)

   打開merge功能 ==========>   如果是maponly 任務,merge功能預設打開;如果是mapreduce任務,需要打開merge功能

                                                      merge功能就是   執行完任務後,自動将小于16M的檔案,合并到256M (hive塊的大小)

5.合理設定map個數和reduce個數

6.啟用壓縮                                                                 好處:減少磁盤空間,減少網絡傳輸      壞處:增加了解壓縮的計算

7.采用列式存儲orc,parquet                                提高查詢效率;提高壓縮比例

8.在map端開啟 combiner            set hive.map.aggr = true

hive 小表與大表關聯

關于小表join大表的補充:

表join時的操作是這樣的:一般是驅動表和另一張表,另一張表最好是小表,将另一張表加載入記憶體。在驅動表裡每行比對的時候,全表掃描小表。

a left outer join b        a是驅動表,b應是小表

a right outer join b      b是驅動表,a應是小表

執行MR或聚集查詢卡死

yarn節點配置設定給nodemanager運作資源的記憶體不夠,就易出現執行MR卡死的狀況,

調整參數 yar.nodemanager.resource.memory-mb  (叢集中某個計算節點配置設定給nodemanager的最大可用記憶體,這個最大可用記憶體不是該節點最大記憶體,而是該節點最大記憶體劃分出來的給nodemanager使用的記憶體)

繼續閱讀