hive是基於Hadoop的一個數據倉庫工具,能夠將結構化的數據文件映射爲一張數據庫表,並提供簡單的sql查詢功能,能夠將sql語句轉換爲MapReduce任務進行運行。
Metastore (hive元數據)
Hive將元數據存儲在數據庫中,好比mysql ,derby.Hive中的元數據包括表的名稱,表的列和分區及其屬性,表的數據所在的目錄
Hive數據存儲在HDFS,大部分的查詢、計算由mapreduce完成
Hive數據倉庫於數據庫的異同
(1)因爲Hive採用了SQL的查詢語言HQL,所以很容易將Hive理解爲數據庫。其實從結構上來看,Hive和數據庫除了擁有相似的查詢語言,
再無相似之處。
(2)數據存儲位置。 hdfs raw local fs
(3)數據格式。 分隔符
(4)數據更新。hive讀多寫少。Hive中不支持對數據的改寫和添加,全部的數據都是在加載的時候中肯定好的。
INSERT INTO … VALUES添加數據,使用UPDATE … SET修改數據 不支持的
HDFS 一次寫入屢次讀取
(5) 執行。hive經過MapReduce來實現的 而數據庫一般有本身的執行引擎。
(6)執行延遲。因爲沒有索引,須要掃描整個表,所以延遲較高。另一個致使Hive執行延遲高的因素是MapReduce框架
(7)可擴展性
(8)數據規模。
hive幾種基本表類型:內部表、外部表、分區表、桶表
內部表(管理表)和外部表的區別:
建立表
外部表建立表的時候,不會移動數到數據倉庫目錄中(/user/hive/warehouse),只會記錄表數據存放的路徑
內部表會把數據複製或剪切到表的目錄下
刪除表
外部表在刪除表的時候只會刪除表的元數據信息不會刪除表數據
內部表刪除時會將元數據信息和表數據同時刪除
表類型1、管理表或內部表Table Type: MANAGED_TABLEmysql
create table if not exists dept( deptno int, deptname string, address string ) row format delimited fields terminated by '\t'; //加載HDFS文件到Hive表中 load data inpath '/input/dept.txt' into table dept; //用來指定原文件的列分隔符 row format delimited fields terminated by '\t'; load 若是操做的HDFS上的文件,表明着會移動或者剪切文件 desc formatted dept; //描述表結構信息 Location: hdfs://bigdata/user/hive/warehouse/db01.db/dept Table Type: MANAGED_TABLE
表類型2、外部表linux
create external table emp( empno int, empname string, empjob string, mgno int, birthday string, salary float, bonus float, depno int ) row format delimited fields terminated by '\t' location '/input/demo'; //描述表結構 desc formatted emp; Location: hdfs://bigdata/input/demo Table Type: EXTERNAL_TABLE 刪除內部表 drop table dept; 刪除外部表 drop table emp; 清空表數據 truncate table student;
表類型3、分區表
分區表建立表的時候須要指定分區字段,分區字段與普通字段的區別:分區字段會在HDFS表目錄下生成一個分區字段名稱的目錄,而普通字段則不會,查詢的時候能夠當成普通字段來使用,通常不直接和業務直接相關。算法
create table emp_part( empno int, empname string, empjob string, mgrno int, birthday string, salary float, bonus float, deptno int ) partitioned by (province string) row format delimited fields terminated by '\t'; //向分區表加載數據 load data local inpath '/home/user01/emp.txt' into table emp_part partition (province='CHICAGO'); //描述表信息 desc formatted emp_part; //查詢全表數據 select * from emp_part; //查詢分區字段表數據 select * from emp_part where province='CHICAGO'; //查看分區信息 show partitions emp_part; //增長分區 aler table emp_part add [if not exist] partition(provine='zhejiang',city='hangzhou') //刪除分區 aler table emp_part drop [if exist] partition(provine='zhejiang',city='hangzhou')
外部分區表
sql
create external table dept_part( deptno int, deptname string, address string ) partitioned by (province string) row format delimited fields terminated by '\t' location '/input/demo'; //手動增長分區字段及外部目錄: alter table dept_part add partition (province='BOSTON') location '/input/demo/BOSTON'; //手動增長分區字段(自動生成分區目錄) alter table dept_part add partition (province='NEW YORK');
表類型四:桶表
將內部表,外部表和分區表進一步組織成桶表
能夠將表的列經過Hash算法進一步分解成不一樣的文件存儲數據庫
create table test_bucket_table( id int, name string ) clustered by (id) into 5 bucket;
建立表的方式
方式一 create + loadapache
create [external] table table_name( col1_name col1_type, ... coln_name coln_type ) row format delimited fields terminated by '\t'; //load加載數據 laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
方式二 like + load緩存
//複製表結構 create table tableB like tableA; //首先必需要有tableA //load加載數據 laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
方式三 as 建立表的同時加載數據服務器
create table emp_insert( id int, name string, job string, salary float ) row format delimited fields terminated by ','; //insert into 加載數據 insert into table emp_insert select empno,empname,empjob,salary from emp_part1 where day='20170308' and hour='14';
方式四 create + insert
//建立表app
create table emp_insert( id int, name string, job string, salary float ) row format delimited fields terminated by ','; //insert into 加載數據 insert into table emp_insert select empno,empname,empjob,salary from emp_part1 where day='20170308' and hour='14';
加載數據的方式
加載方式一框架
//加載本地文件到Hive表 --使用存儲介質(移動硬盤) laod data local inpth '本地文件(linux)' [overwrite] into table table_name;
加載方式二
//建立表時經過select查詢語句加載數據 create table tableB row format delimited filelds termianted by ',' as select * from tableA;
加載方式三
//建立表時經過select查詢語句加載數據 create table tableB row format delimited filelds termianted by ',' as select * from tableA;
加載方式四
//建立表時經過select查詢語句加載數據 create table tableB row format delimited filelds termianted by ',' as select * from tableA;
加載方式五
//先建立表,經過insert into table table_namea select * fom tableB
加載方式六
<property> <name>hive.fetch.task.conversion</name> <value>more</value> <description> Some select queries can be converted to single FETCH task minimizing latency.Currently the query should be single sourced not having any subquery and should not have any aggregations or distincts (which incurrs RS), lateral views and joins. 1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only 2. more : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns) </description> </property>
幾種導出數據的方式
1.insert overwrite ... 導出到本地目錄
insert overwrite local directory '/home/user01/export' row format delimited fields terminated by ' ' select * from emp_part1;
2.insert overwrite ... 導出到HDFS之上
insert overwrite directory '/export' select * from emp_part1 where day='20170308';
3.hive -e 'HQL query' >> test
bin/hive -e 'select * from db01.student' >> test.txt
4)sqoop
Hive 自定義函數函數
UDF 一進一出 處理原文件內容某些字段包含 [] 「」
UDAF 多進一出 sum() avg() max() min()
UDTF 一進多出 ip -> 國家 省 市
Hive4種排序
order by //能夠指定desc 降序 asc 升序
order by會對輸入作全局排序,所以只有一個Reducer(多個Reducer沒法保證全局有序),然而只有一個Reducer,會致使當輸入規模較大時,消耗較長的計算時間。
sort by 【對分區內的數據進行排序】
sort by不是全局排序,其在數據進入reducer前完成排序,所以,若是用sort by進行排序,而且設置mapred.reduce.tasks>1,則sort by只會保證每一個reducer的輸出有序,並不保證全局有序。sort by不一樣於order by,它不受Hive.mapred.mode屬性的影響,sort by的數據只能保證在同一個reduce中的數據能夠按指定字段排序。使用sort by你能夠指定執行的reduce個數(經過set mapred.reduce.tasks=n來指定),對輸出的數據再執行歸併排序,便可獲得所有結果。
distribute by 【對map輸出進行分區】
distribute by是控制在map端如何拆分數據給reduce端的。hive會根據distribute by後面列,對應reduce的個數進行分發,默認是採用hash算法。sort by爲每一個reduce產生一個排序文件。在有些狀況下,你須要控制某個特定行應該到哪一個reducer,這一般是爲了進行後續的彙集操做。distribute by恰好能夠作這件事。所以,distribute by常常和sort by配合使用。
cluster by
cluster by除了具備distribute by的功能外還兼具sort by的功能。當distribute by和sort by 是同一個字段的時候可使用cluster by替代。可是排序只能是倒敘排序,不能指定排序規則爲ASC或者DESC。
三種分組的區別
row_number:無論col2字段的值是否相等,行號一直遞增,好比:有兩條記錄的值相等,但一個是第一,一個是第二
rank:上下兩條記錄的col2相等時,記錄的行號是同樣的,但下一個col2值的行號遞增N(N是重複的次數),好比:有兩條並列第一,下一個是第三,沒有第二
dense_rank:上下兩條記錄的col2相等時,下一個col2值的行號遞增1,好比:有兩條並列第一,下一個是第二
Hive優化
1.fetch task任務不走MapReduce,能夠在hive配置文件中設置最大化和最小化fetch task任務;一般在使用hiveserver2時調整爲more;
設置參數的優先級:在命令行或者代碼設置參數 > hive-site.xml>hive-default.xml
set hive.fetch.task.conversion=more; //單次交互模式下有效,
bin/hive --hiveconf hive.fetch.task.conversion=more
上面的兩種方法均可以開啓了Fetch任務,可是都是臨時起做用的;若是你想一直啓用這個功能,能夠在${HIVE_HOME}/conf/hive-site.xml裏面加入如下配置:
<property> <name>hive.fetch.task.conversion</name> <value>more</value> <description> Some select queries can be converted to single FETCH task minimizing latency.Currently the query should be single sourced not having any subquery and should not have any aggregations or distincts (which incurrs RS), lateral views and joins. 1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only 2. more : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns) </description> </property>
2.strict mode:嚴格模式設置,嚴格模式下將會限制一些查詢操做
文件格式,ORC PARQUET 等
分區表
select 查詢不加where過濾條件,不會執行
開啓嚴格模式
hive提供的嚴格模式,禁止3種狀況下的查詢模式。
a:當表爲分區表時,where字句後沒有分區字段和限制時,不容許執行。
b:當使用order by語句時,必須使用limit字段,由於order by 只會產生一個reduce任務。
c:限制笛卡爾積的查詢。sql語句不加where不會執行
<property> <name>hive.mapred.mode</name> <value>nonstrict</value> <description>The mode in which the Hive operations are being performed. In strict mode, some risky queries are not allowed to run. They include: Cartesian Product. No partition being picked up for a query. Comparing bigints and strings. Comparing bigints and doubles. Orderby without limit. </description> </property>
3.優化sql語句,如先過濾再join,先分組再作distinct;
Select count(*) cnt From store_sales ss join household_demographics hd on (ss.ss_hdemo_sk = hd.hd_demo_sk) join time_dim t on (ss.ss_sold_time_sk = t.t_time_sk) join store s on (s.s_store_sk = ss.ss_store_sk) Where t.t_hour = 8 t.t_minute >= 30 hd.hd_dep_count = 2 order by cnt;
4.MapReduce過程的map、shuffle、reduce端的snappy壓縮
須要先替換hadoop的native本地包開啓壓縮
在mapred-site.xml文件設置啓用壓縮及壓縮編碼
在執行SQL執行時設置啓用壓縮和指定壓縮編碼
set mapreduce.output.fileoutputformat.compress=true; set mapreduce.output.fileoutputformat.compress.codec=org apache.hadoop.io.compress.SnappyCodec;
5.大表拆分紅子表,提取中間結果集,減小每次加載數據
多維度分析,多個分析模塊
每一個分析模塊涉及字段不同,並且並非表的所有字段
6.分區表及外部表
設計二級分區表(一級字段爲天,二級字段設置小時)
建立的的是外部表,建立表時直接指定數據所在目錄便可,不用再用load加載數據
7.設置map和reduce個數:默認狀況下一個塊對應一個map任務,map數據咱們通常不去調整,reduce個數根據reduce處理的數據量大小進行適當調總體現「分而治之」的思想
hive-site.xml hive.mapred.reduce.tasks.speculative.execution=true; <property> <name>hive.mapred.reduce.tasks.speculative.execution</name> <value>true</value> <description>Whether speculative execution for reducers should be turned on. </description> </property>
8.JVM重用:一個job可能有多個map reduce任務,每一個任務會開啓一個JVM虛擬機,默認狀況下一個任務對應一個JVM,任務運行完JVM即銷燬,咱們能夠設置JVM重用參數,通常不超過5個,這樣一個JVM內能夠連續運行多個任務
JVM重用是Hadoop調優參數的內容,對Hive的性能具備很是大的影響,特別是對於很難避免小文件的場景或者task特別多的場景,這類場景大多數執行時間都很短。hadoop默認配置是使用派生JVM來執行map和reduce任務的,這是jvm的啓動過程可能會形成至關大的開銷,尤爲是執行的job包含有成千上萬個task任務的狀況。
JVM重用可使得JVM實例在同一個JOB中從新使用N次,N的值能夠在Hadoop的mapre-site.xml文件中進行設置(建議參考5~10)
mapred.job.reuse.jvm.num.tasks(舊版)
mapreduce.job.jvm.numtasks(新版)
hadoop.apache.org/docs/r2.5.2/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
http://hadoop.apache.org/docs/r2.5.2/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
也可在hive的執行設置:
hive-site.xml hive.mapred.reduce.tasks.speculative.execution=true; <property> <name>hive.mapred.reduce.tasks.speculative.execution</name> <value>true</value> <description>Whether speculative execution for reducers should be turned on. </description> </property>
9.推測執行:例如一個Job應用有10個MapReduce任務(map 及reduce),其中9個任務已經完成,那麼application Master會在另外啓動一個相同的任務來運行未完成的那個,最後哪一個先運行完成就把另外一個kill掉
啓用speculative最大的好處是,一個map執行的時候,系統會在其餘空閒的服務器上啓動相同的map來同時運行,哪一個運行的快就使用哪一個的結果,另外一個運行慢的在有告終果以後就會被kill。
hive-site.xml hive.mapred.reduce.tasks.speculative.execution=true; <property> <name>hive.mapred.reduce.tasks.speculative.execution</name> <value>true</value> <description>Whether speculative execution for reducers should be turned on. </description> </property>
數據傾斜
對於普通的join操做,會在map端根據key的hash值,shuffle到某一個reduce上去,在reduce端作join鏈接操做,內存中緩存join左邊的表,遍歷右邊的表,依次作join操做。因此在作join操做時候,將數據量多的表放在join的右邊。
當數據量比較大,而且key分佈不均勻,大量的key都shuffle到一個reduce上了,就出現了數據的傾斜。
常見的數據傾斜出如今group by和join..on..語句中。
join(數據傾斜)
在進行兩個表join的過程當中,因爲hive都是從左向右執行,要注意講小表在前,大表在後(小表會先進行緩存)。
map/reduce程序執行時,reduce節點大部分執行完畢,可是有一個或者幾個reduce節點運行很慢,致使整個程序的處理時間很長,這是由於某一個key的條數比其餘key多不少(有時是百倍或者千倍之多),這條key所在的reduce節點所處理的數據量比其餘節點就大不少,從而致使某幾個節點遲遲運行不完,此稱之爲數據傾斜。hive在跑數據時常常會出現數據傾斜的狀況,使的做業常常reduce完成在99%後一直卡住,最後的1%花了幾個小時都沒跑完,這種狀況就極可能是數據傾斜的緣由,
hive.groupby.skewindata=true;
若是是group by過程出現傾斜應將此項設置true。
<property>
<name>hive.groupby.skewindata</name>
<value>false</value>
<description>Whether there is skew in data to optimize group by queries</description>
</property>
hive.optimize.skewjoin.compiletime=true;
若是是join 過程當中出現傾斜應將此項設置爲true
不影響結果能夠考慮過濾空值
<property>
<name>hive.optimize.skewjoin.compiletime</name>
<value>false</value>
</property>
hive.optimize.skewjoin.compiletime=true; 若是是join過程出現傾斜應該設置爲true
此時會將join語句轉化爲兩個mapreduce任務,第一個會給jion字段加隨機散列
set hive.skewjoin.key=100000; 這個是join的鍵對應的記錄條數超過這個值則會進行優化。
能夠在空值前面加隨機散列
3種常見的join
Map-side Join
mapJoin的主要意思就是,當連接的兩個表是一個比較小的表和一個特別大的表的時候,咱們把比較小的table直接放到內存中去,而後再對比較大的表格進行map操做。join就發生在map操做的時候,每當掃描一個大的table中的數據,就要去去查看小表的數據,哪條與之相符,繼而進行鏈接。這裏的join並不會涉及reduce操做。map端join的優點就是在於沒有shuffle,真好。在實際的應用中,咱們這樣設置:
***1. set hive.auto.convert.join=true;
這樣設置,hive就會自動的識別比較小的表,繼而用mapJoin來實現兩個表的聯合。看看下面的兩個表格的鏈接。
<property>
<name>hive.auto.convert.join.noconditionaltask.size</name>
<value>10000000</value> The default is 10MB
</property>
DistributedCache是分佈式緩存的一種實現,它在整個MapReduce框架中起着至關重要的做用,他能夠支撐咱們寫一些至關複雜高效的分佈式程
這裏的第一句話就是運行本地的map join任務,繼而轉存文件到XXX.hashtable下面,在給這個文件裏面上傳一個文件進行map join,以後才運行了MR代碼去運行計數任務。說白了,在本質上mapjoin根本就沒有運行MR進程,僅僅是在內存就進行了兩個表的聯合。
mapjoin使用場景
1.關聯操做中有一張表很是小
2.不等值的連接操做
自動執行
set hive.auto.convert.join=true; hive.mapjoin.smalltable.filesize=25;默認值是25mb
<property>
<name>hive.mapjoin.smalltable.filesize</name>
<value>25000000</value>
</property>
手動執行 A爲小表 若是A表超過25M,還想使用map join;
select /+mapjoin(A)/ f.a,f.b from A t join B f on(f.a==t.a)
hive入門學習:join的三種優化方式 - HAHA的專欄 - 博客頻道 - CSDN.NET
http://blog.csdn.net/liyaohhh/article/details/50697519
Reduce-side Join
***hive join操做默認使用的就是reduce join
Reduce-side Join原理上要簡單得多,它也不能保證相同key但分散在不一樣dataset中的數據可以進入同一個Mapper,整個數據集合的排序
在Mapper以後的shuffle過程當中完成。相對於Map-side Join,它不須要每一個Mapper都去讀取全部的dataset,這是好處,但也有壞處,
即這樣一來Mapper以後須要排序的數據集合會很是大,所以shuffle階段的效率要低於Map-side Join。
***reduce side join是一種最簡單的join方式,其主要思想以下:
在map階段,map函數同時讀取兩個文件File1和File2,爲了區分兩種來源的key/value數據對,對每條數據打一個標籤(tag)
semi join 小表對大表 是reudce join的變種 map階段過濾掉不須要join的字段 至關於Hivw SQL加的where過濾
SMB Join(sort merge bucket)
SMB 存在的目的主要是爲了解決大表與大表間的 Join 問題,分桶其實就是把大表化成了「小表」,而後 Map-Side Join 解決之,這是典型的分而治之的思想。
1 set hive.enforce.bucketing=true; 2 set hive.enforce.sorting=true;
表優化數據目標:相同數據儘可能彙集在一塊兒