Hive基础
為什么80%的碼農都做不了架構師?>>> ??
Hive架構簡介
? ? 下圖是hive的架構圖
命令執行
所有的命令和查詢都會進入到Driver,通過這個模塊進行解析編譯,對需求的計算進行優化。然后按照指定的步驟執行(通常是啟動多個MapReduce任務(JOB)來執行)。當需要啟動 MapReduce任務(job)時,HIVE 本身不會生成Java MapReduve算法程序。相反,Hive通過一個表示“JOB執行計劃”的。XML文件驅動執行內置的、原生的Mapper和Reducer模塊。換句話說,這些通用的模塊函數類似于微型的語言翻譯程序,二驅動計算的“語言”是以XML形式編碼的。Hive 通過和JobTracker通信來初始化MapReduve任務(job),而不必部署在JobTracker所在的管理節點上執行。要處理的數據文件是存儲在HDFS中的,而HDFS是由NameNode進行管理的。
驅動器:Dirver 包含:解析器、編譯器、優化器、執行器
解析器:將SQL字符串轉換成抽象語法樹AST,這一步一般都是用第三方工具庫完成,比如antlr;對AST語 ? ? ? ? ? ? ? 法樹進行分析,比如表否存在、字段是否存在、SQL語義是否有誤。
編譯器:將AST編譯生成邏輯執行計劃。
優化器:對邏輯執行計劃進行優化。
執行器:把邏輯執行計劃轉換成物理執行計劃。對于hive來說,就是MR/TEZ/Spark;
元數據
Metastore是一個獨立的關系型數據庫,通常使用MYSQL。Hive 會在其中保存表模式和其他系統元數據中的。元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否為外部表等),表的數據所在目錄等
?
Hive數據類型
????hive基礎數據類型
? ? ? hive是用java開發的,hive里的基本數據類型和java的基本數據類型也是一一對應的,除了string類型。有符號的整數類型:TINYINT、SMALLINT、INT和BIGINT分別等價于java的byte、short、int和long原子類型,它們分別為1字節、2字節、4字節和8字節有符號整數。Hive的浮點數據類型FLOAT和DOUBLE,對應于java的基本類型float和double類型。而hive的BOOLEAN類型相當于java的基本數據類型boolean。
????hive復雜數據類型
? ? ? ?包括ARRAY,MAP,STRUCT,UNION。這些復雜類型是由基礎類型組成的。
? ? ? ?ARRAY:ARRAY類型是由一系列同樣數據類型元素組成的,這些元素能夠通過下標來訪問。比方有一個ARRAY類型的變量fruits。它是由[‘apple’,’orange’,’mango’]組成,那么能夠通過fruits[1]來訪問orange。
? ? ? ?MAP:MAP包括key->value鍵值對。能夠通過key來訪問元素。比方userlist是一個map類型(當中username是key。password是value),那么我們能夠通過userlist[username]來得到這個用戶相應的password.。
? ? ? STRUCT:STRUCT能夠包括不同數據類型的元素。這些元素能夠通過點的方式來得到,比方user是一個STRUCT類型,那么能夠通過user.address得到這個用戶的地址。
????????COLLECTION?ITEMS?TERMINATED?BY?',' ? ?//集合元素分隔符
????????MAP?KEYS?TERMINATED?BY?' : ' ? ? ? ? ? ? ? ?//MAP數據類型key:value分割符
Hive表類型
????? 內部表
????????????內部表也稱之為MANAGED_TABLE;默認存儲在/user/hive/warehouse下,也可以通過location指定;刪除表時,會刪除表數據以及元數據;
????? ? ?create table if not exists...
? ? ? ?外部表
???????外部表稱之為EXTERNAL_TABLE在創建表時可以自己指定目錄位置(LOCATION);刪除表時,只會刪除元數據不會刪除表數據;
????? ?create EXTERNAL table if not exists...
????? ?加載數據
????????? ? 注意 導入的路徑必須是hive用戶有訪問權限的路徑,否則會報找不到文件錯誤
? ? ? ? ? ?(1)?HDFS上導入數據到Hive表
? ? ? ? ?? ?(2) 從本地路徑導入數據到Hive表
load?data local inpath 'wyp.txt' into table test ;#使用分區 load?data local inpath '/your/path/test.txt' overwrite into table test partition (age='25')????????????(3)?從別的表查詢加載到hive表
?????????????靜態分區
insert into table test partition (age='25') select id, name, tel from wyp;????????? ? ?動態分區
set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict; insert overwrite table test PARTITION (age) select id, name, tel, age from wyp;????insert into table和insert overwrite table的區別:后者會覆蓋相應數據目錄下的數據將。
????創建相似表
create table table_name like other_table_name location "xxxxx"????查詢數據輸出到本地目錄
INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='<DATE>';select *from emp distribute by deptno sort by empno asc ;
cluster by ?= distribute by 和 sort by 值相同。
Hive UDF編程
????UDF(user defined function).hive的UDF包含三種:UDF支持一個輸入產生一個輸出,UDTF支持一個輸入多個輸出輸出(一行變多行),UDAF支持多輸入一輸出(多行變一行)。
? ?UDF 簡單實現
? 編程步驟:
????1、繼承org.apache.hadoop.hive.ql.UDF
????2、需要實現evaluate函數; evaluate函數支持重載;
? 注意事項:
????1、 UDF必須要有返回類型,可以返回null,但是返回類型不能為void;
????2、 UDF中常用Text/LongWritable等類型,不推薦使用java類型;
? ? 官網demo: ?https://cwiki.apache.org/confluence/display/Hive/HivePlugins
? 使用UDF非常簡單,只需要繼承org.apache.hadoop.hive.ql.exec.UDF,并定義public Object evaluate(Object args) {} 方法即可。
? ? ?比如,下面的UDF函數實現了對一個String類型的字符串取HashMD5:
package?com.lxw1234.hive.udf;import?org.apache.hadoop.hbase.util.Bytes; import?org.apache.hadoop.hbase.util.MD5Hash; import?org.apache.hadoop.hive.ql.exec.UDF;public?class?HashMd5?extends?UDF?{public?String?evaluate(String?cookie)?{return?MD5Hash.getMD5AsHex(Bytes.toBytes(cookie));}public?String?evaluate(String?cookie1,String cookie2)?{return?MD5Hash.getMD5AsHex(Bytes.toBytes(cookie1,cookie2));}}將上面的HashMd5類打成jar包,udf.jar
使用時候,在Hive命令行執行:
hive> add jar file:///tmp/udf.jar; hive> CREATE temporary?function?str_md5?as?'com.lxw1234.hive.udf.HashMd5'; hive> select?str_md5(‘lxw1234.com’)?from?dual;?
? ? Transform
? ? ?Hive中的TRANSFORM:使用腳本完成Map/Reduce。
hive> add file python文件路徑 hive> SELECTTRANSFORM(p.joint_attr_values,?p.collect_product_id,?p.released_id)??USING?'python?split_product_attrs.py'??as?(custom_attr?,?custom_attr_value,?collect_product_id,?released_product_id)??from???(??這里應該是另外一個select語句,用于Transform的輸入,最好是一一對應的,否則會出錯??)??? ?注意:python腳本一定要先加載:hive>ADD FILE python_file_path [注意此處的path不要加''上引號]
? ? 下面是python的腳本,用于將三列轉換為四列,這里就比較簡單了,主要用于測試,代碼隨便寫了一下
#!/usr/bin/python # #_*_ coding: utf-8 _*_ import sys import datetime # "規格:RN1-10/50;規格:RN1-10/50;規格:RN1-10/50" # ["規格:RN1-10/51;規格:RN1-10/52;規格:RN1-10/53", '11', '22'] # ["規格", "RN1-10/51", '11', '22'] # ["規格", "RN1-10/52", '11', '22'] # ["規格", "RN1-10/53", '11', '22'] for line in sys.stdin: values = line.split('\t') values = [ i.strip() for i in values ] tmp = values[0] key_values = tmp.split(";") for kv in key_values: k = kv.split(":")[0] v = kv.split(":")[1] print '\t'.join([k,v,values[1],values[2]])?
Hive企業優化方案
Hive存儲格式
???1、TEXTFILE ? 默認格式,建表時不指定默認為這個格式,導入數據時會直接把數據文件拷貝到hdfs上不進行處理。只有TEXTFILE表能直接加載數據,本地load數據,和external外部表直接加載運路徑數據,都只能用TEXTFILE表。更深一步,hive默認支持的壓縮文件(hadoop默認支持的壓縮格式),也只能用TEXTFILE表直接讀取。其他格式不行。可以通過TEXTFILE表加載后insert到其他表中。
? 2、orc?格式。? ?STORED AS ORC?; ?
? 3、parquet 格式。 STORED AS PARQUET ;
?幾種格式的差別 ?http://www.cnblogs.com/juncaoit/p/6067646.html
?
Hive壓縮優化
hive壓縮相關博客??https://yq.aliyun.com/articles/60859
壓縮配置:
?map/reduce?輸出壓縮(一般采用序列化文件存儲)?
set hive.exec.compress.output=true;set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;set mapred.output.compression.type=BLOCK;任務中間壓縮? ?
set hive.exec.compress.intermediate=true;set hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;(常用)set hive.intermediate.compression.type=BLOCK;中間壓縮
中間壓縮就是處理作業map任務和reduce任務之間的數據,對于中間壓縮,最好選擇一個節省CPU耗時的壓縮方式
<property><name>hive.exec.compress.intermediate</name><value>true</value> </property>hadoop壓縮有一個默認的壓縮格式,當然可以通過修改mapred.map.output.compression.codec屬性,使用新的壓縮格式,這個變量可以在mapred-site.xml?中設置或者在 hive-site.xml文件。 SnappyCodec?是一個較好的壓縮格式,CPU消耗較低。
<property><name>mapred.map.output.compression.codec</name><value>org.apache.hadoop.io.compress.SnappyCodec</value> </property>?
?MapReduce中使用壓縮
????
?Hive中 使用壓縮
????????
關閉推測執行
? ? ? ? (1) 修改mapred-site.xml
????????? ? ?mapreduce.map.speculative ? ? false
?????????????mapreduce.reduce.speculative? ? false
??????? (2) 設置值
????????????set hive.mapred.reduce.tasks.speculative.execution=false;
????? ? (3) set hive.exec.mode.local.auto=true??決定 Hive 是否應該自動地根據輸入文件大小,在本地運行。
?
Hive 數據傾斜解決方案
? ? ? ?Hive join解釋 ?https://www.cnblogs.com/xing901022/p/5804836.html
? ? ? ? 小表 join 大表 ? ? ? ?大表 join 大表 ?方案
? ? (1)Common/Shuffle/Reduce Join ?
? ? ? 普通mapreduce join ,相同key分配到同一個reducer。
? ? (2) Map Join ?
? ? ? MAPJION會把小表全部讀入內存中,在map階段直接拿另外一個表的數據和內存中表數據做匹配,適用于小表join 大表。
set hive.auto.convert.join=false; set hive.ignore.mapjoin.hint=false;????Sql可以通過使用hint的方式指定join時使用mapjoin,其中mapjoin選中的表為小表
? ?select?/*+ mapjoin(t1)*/?t1.a,t1.b?from?table?t1?join?table2?t2??on?(?t1.a=t2.a?and t1.time=201108)?
? ? ?Map Join Java實現??http://www.cnblogs.com/ivanny/p/mapreduce_join.html
? ?(3) ?SMB Join (Sort Merge Bucket Join)
? ? ?使用SMB兩個表必須使用桶分區,使用 SMB Join 需要如下配置
set hive.enforce.bucketing = true; //強制使用桶表 set hive.auto.convert.sortmerge.join=true; set hive.optimize.bucketmapjoin = true; set hive.optimize.bucketmapjoin.sortedmerge = true;? ?select?/*+ mapjoin(t1)*/?t1.a,t1.b?from?table?t1?join?table2?t2??on?(?t1.a=t2.a?and t1.time=201108)?
? ? 1. 兩個表關聯鍵為id,需要按id分桶并且做排序,小表的分桶數是大表分桶數的倍數。?
????2. 對于map端連接的情況,兩個表以相同方式劃分桶。處理左邊表內某個桶的 mapper知道右邊表內相匹配的行在對應的桶內。因此,mapper只需要獲取那個桶 (這只是右邊表內存儲數據的一小部分)即可進行連接。這一優化方法并不一定要求 兩個表必須桶的個數相同,兩個表的桶個數是倍數關系也可以。
???3. 桶中的數據可以根據一個或多個列另外進行排序。由于這樣對每個桶的連接變成了高效的歸并排序(merge-sort), 因此可以進一步提升map端連接的效率。
Hive分區
? ?參數設置
#開啟動態分區 set hive.exec.hynamic.partition=true; #注:這個屬性默認是strict,即限制模式,strict是避免全分區字段是動態的,必須至少一個分區字段是指定有值即靜態的,且必須放在最前面。設置為nonstrict之后所有的分區都可以是動態的了。 set hive.exec.dynamic.partition.mode=nonstrict;#注:這個屬性表示每個節點生成動態分區的最大個數,默認是100 SET hive.exec.max.dynamic.partitions=100000;#注:這個屬性表示每個節點生成動態分區的最大個數,默認是100 SET hive.exec.max.dynamic.partitions.pernode=100000;#注:這個屬性表示一個DML操作可以創建的最大文件數,默認是100000 set hive.exec.max.created.files=150000?
建表
create table user_info (user_id int, cid string, ckid string, username string) row format delimited fields terminated by '\t' lines terminated by '\n';1.行格式化 2.字段通過'\t' 分割 3.行通過'\n' 分隔開# flume 收集 建表方案
create table baoertest(user_agent string,user_id bigint,time string) partitioned by (year string, month string, day string) clustered by (user_id) into 5 buckets stored as orc tblproperties("transactional"="true"); ? #使用這個,不能使用insert overwrite,可以使用insert,delete# insert overwrite table 建表方案 ?prestodb可識別
create table baoertest(user_agent string,user_id bigint,time string) partitioned by (year string, month string, day string) clustered by (user_id) into 5 buckets stored as orc;set hive.enforce.bucketing=true;? ? ? ? ? ? ? #? 使用桶,需要強制設置
set mapreduce.job.reduces=<number>? ?#? 設置reduces個數?
#靜態分區
--data.txt--
chrome?? ?112212123?? ?11-12
windows?? ?123123123?? ?11-11
#動態分區
--data01.txt--
chrome?? ?112212123?? ?11-12?? ?2017?? ?05?? ?21
windows?? ?123123123?? ?11-11?? ?2017?? ?06?? ?19
#查詢使用分區
?當分區建立后,查詢可直接使用分區字段 ?
? ? select *from baoertest where year=xxx and month=xxx and day=xxx
#手動添加分區(? 外部表需要手動添加分區? ?)
? ? alter table ?table_xxx ?add partition (dt='2016-09-12');
#手動刪除分區( 刪除分區 非外部表會同時刪除分區的HDFS數據 )
? ? alter table ?table_xxx ?drop partition (month=2017,month=10,day=21);
#自動添加分區,根據HDFS目錄名
? ??MSCK?REPAIR?TABLE?table_name
? ?執行后,Hive會檢測如果HDFS目錄下存在但表的metastore中不存在的partition元信息,更新到metastore中
Hive 修改表
????? ? #修改表的location url
????????alter table test? set location 'hdfs://heracles/user/video-mvc/hive/warehouse/t_m_cc'
轉載于:https://my.oschina.net/manmao/blog/1559003
總結
- 上一篇: 使用nhmicro提供的micro-da
- 下一篇: IO多路复用原理剖析