一虚吟、HIVE簡介
Hive是一種建立在Hadoop文件系統上的數據倉庫架構谒兄,并對存儲在HDFS中的數據進行分析和管理笑诅;它可以將結構化的數據文件映射為一張數據庫表靠益,并提供完整的 SQL 查詢功能妒蔚,可以將 SQL 語句轉換為 MapReduce 任務進行運行穿挨,通過自己的 SQL 去 查詢分析需要的內容月弛,這套 SQL 簡稱 Hive SQL(HQL),使不熟悉 MapReduce 的用戶也能很方便地利用 SQL 語言對數據進行查詢科盛、匯總帽衙、分析。同時贞绵,這個語言也允許熟悉 MapReduce 開發(fā)者們開發(fā)自定義的mappers和reducers來處理內建的mappers和reducers無法完成的復雜的分析工作厉萝。Hive還允許用戶編寫自己定義的函數UDF,用來在查詢中使用榨崩。Hive中有3種UDF:User Defined Functions(UDF)谴垫、User Defined Aggregation Functions(UDAF)、User Defined Table Generating Functions(UDTF)母蛛。也就是說對存儲在HDFS中的數據進行分析和管理翩剪,我們不想使用手工,我們建立一個工具吧彩郊,那么這個工具就可以是hive前弯。
二、簡單的命令
//展示方法名列表
show functions;
//簡單方法的解釋
desc function split;
//解釋方法名并且舉個例子
desc function extended split;
//查找sp開頭的方法名
show functions like 'sp.*';
三秫逝、分區(qū)和分桶
1.分區(qū)
(1)什么是分區(qū)恕出?
分區(qū)其實就是再HDFS上存儲的時候分了一個相應的分區(qū)文件夾,比如你的一個表 partition_test,然后根據日期分區(qū)的話违帆,最后HDFS上的就是類似這樣的結構
/user/hive/warehouse/partition_test/stat_date=2015-01-18/province=beijing----顯示剛剛創(chuàng)建的分區(qū)
(2)內部表和外部表有什么區(qū)別浙巫?
1.內部表刪除的時候會將表的數據和元數據信息全部刪除,而外部表僅僅刪除外部表的元數據前方,數據是不會刪除的狈醉。
- 內部表在load data的時候會將數據轉移。也就是說 load data inpath '/input/edata' into table et; 這句話會把HDFS上的/input/edata文件移動到表et的location下面惠险。而外部表不會苗傅。
3.內部表和外部表都會在 /user/hive/warehouse/新建一個表的目錄(如果不指定location的話)
(3)內部分區(qū)表和外部分區(qū)表
創(chuàng)建一個簡單的內部分區(qū)表
create table partition_internal(
id INT COMMENT 'student id',
name STRING COMMENT 'student name',
age INT COMMENT 'student age')
PARTITIONED BY(province STRING,city STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
//為內部分區(qū)表指定分區(qū)
ALTER TABLE partition_internal ADD PARTITION (province='henan',city='zhengzhou');
//加載數據到內部分區(qū)表 這個時候會移動數據
LOAD DATA INPATH '/user/hive/external01' INTO TABLE partition_internal PARTITION(province='henan',city='zhengzhou');
創(chuàng)建外部分區(qū)表
create external table partition_external(
id INT COMMENT 'student id',
name STRING COMMENT 'student name',
age INT COMMENT 'student age')
PARTITIONED BY(province STRING,city STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
create external table partition_external(
id INT COMMENT 'student id',
name STRING COMMENT 'student name',
age INT COMMENT 'student age')
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION '/user/hive/external02';
為外部分區(qū)表添加分區(qū)
ALTER TABLE partition_external ADD PARTITION (province='shanxi',city='xian') LOCATION '/user/hive/external02';
//查看分區(qū)
show partitions partition_external;
//刪除分區(qū)
ALTER TABLE student_partition_external DROP PARTITION(province='guangzhou',city='shenzhen');
//向多個分區(qū)插入數據,命令如下班巩。
from partition_test_input
insert overwrite table partition_test partition(stat_date='2015-01-18',province='jiangsu') select member_id,name from partition_test_input where stat_date='2015-01-18' and province='jiangsu'
insert overwrite table partition_test partition(stat_date='2015-01-28',province='sichuan') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='sichuan'
insert overwrite table partition_test partition(stat_date='2015-01-28',province='beijing') select member_id,name from partition_test_input where stat_date='2015-01-28' and province='beijing';
(4)動態(tài)分區(qū)
按照上面的方法向分區(qū)表中插入數據渣慕,如果數據源很大,針對一個分區(qū)就要寫一個 insert 抱慌,非常麻煩逊桦。使用動態(tài)分區(qū)可以很好地解決上述問題。動態(tài)分區(qū)可以根據查詢得到的數據自動匹配到相應的分區(qū)中去抑进。
1强经、啟動動態(tài)分區(qū)功能(默認沒有啟動)
set hive.exec.dynamic.partition = true;
2、設置所有分區(qū)都是動態(tài)的
set hive.exec.dynamic.partition.mode=nostrict;
3寺渗、準備兩個表:一個普通外部表student_external01匿情,一個分區(qū)外部表student02
而且要保證分區(qū)表結構student02和student_external01一致
我們以student_external01表為例兰迫,但是少兩個分區(qū)字段,所以我們再增加兩個字段炬称。
ALTER TABLE student_external01 ADD COLUMNS(province STRING,city STRING);
4汁果、先往外部表student_external01中加載數據(實際上現在外部表student_external01中已經有數據了,因為創(chuàng)建該表時指定了location)
LOAD DATA INPATH '/user/hive/external02/student.txt' INTO TABLE student_external01;
5玲躯、利用動態(tài)分區(qū)向表中插入數據
//先創(chuàng)建分區(qū)外部表student02
create external table student02(
id INT COMMENT 'student id',
name STRING COMMENT 'student name',
age INT COMMENT 'student age')
PARTITIONED BY(province STRING,city STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
//利用動態(tài)分區(qū)向表中插入數據
INSERT OVERWRITE TABLE student02 PARTITION(province,city) SELECT * FROM student_external01 ;
然后數據就會動態(tài)分區(qū)据德,把對應的數據放到對應的分區(qū)下。
2.桶操作
Hive 中 table 可以拆分成 Partition table 和 桶(BUCKET)跷车,分區(qū)提供了一個隔離數據和優(yōu)化查詢的便利方式棘利,不過并非所有的數據都可形成合理的分區(qū),尤其是需要確定合適大小的分區(qū)劃分方式姓赤,(不合理的數據分區(qū)劃分方式可能導致有的分區(qū)數據過多赡译,而某些分區(qū)沒有什么數據的尷尬情況)分桶是將數據集分解為更容易管理的若干部分的另一種技術仲吏。
數據分桶的原理: 跟MR中的HashPartitioner的原理一模一樣, 按照分桶字段的hash值去模除以分桶的個數
和分區(qū)的區(qū)別:分桶中的字段是原始數據中存在的不铆,而分區(qū)字段在原始文件中并不存在。比如我們上面的那個分區(qū)province和city字段就是不在student02中的(如果指定了分區(qū)并且表的字段中還包含這兩個字段的話裹唆,hive會報錯的)
1誓斥、開啟分桶功能
set hive.enforce.bucketing=true;
2、創(chuàng)建桶表
CREATE TABLE IF NOT EXISTS bucket_table(
id INT COMMENT 'student id',
name STRING COMMENT 'student name',
age INT COMMENT 'student age')
CLUSTERED BY(id) INTO 3 BUCKETS
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
3许帐、插入數據到桶表中
INSERT OVERWRITE TABLE bucket_table SELECT id,name,age FROM student_external01;
二.HIVE復合類型
hive提供了復合數據類型:
1.Structs: structs內部的數據可以通過DOT(.)來存取劳坑。例如,表中一列c的類型為STRUCT{a INT; b INT}成畦,我們可以通過c.a來訪問域a距芬。
- 建表
hive> create table student_test(id INT, info struct< name:STRING, age:INT>)
> ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
> COLLECTION ITEMS TERMINATED BY ':';
'FIELDS TERMINATED BY' :字段與字段之間的分隔符。'COLLECTION ITEMS TERMINATED BY' :一個字段各個item的分隔符循帐。
- 導入數據(注意最后不要帶空格不然識別就是NULL)
$ cat test5.txt
1,zhou:30
2,yan:30
3,chen:20
4,li:80
hive> LOAD DATA LOCAL INPATH '/home/hadoop/djt/test5.txt' INTO TABLE student_test;
- 查詢數據
hive> select info.age from student_test;
2.Map(K-V對):訪問指定域可以通過["指定域名稱"]進行框仔。例如,一個Map M包含了一個group-》gid的kv對拄养,gid的值可以通過M['group']來獲取离斩。
- 建表
hive> create table employee(id string, perf map< string, int>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';
‘MAP KEYS TERMINATED BY’ :key value分隔符
- 導入數據
$ cat test7.txt
1 job:80,team:60,person:70
2 job:60,team:80
3 job:90,team:70,person:100
hive> LOAD DATA LOCAL INPATH '/home/work/data/test7.txt' INTO TABLE employee;
- 查詢
hive> select perf['person'] from employee;
3)Array:array中的數據為相同類型。例如瘪匿,假如array A中元素['a','b','c']跛梗,則A[1]的值為'b'
3.Array使用
- 建表
hive> create table class_test(name string, student_id_list array< INT>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
COLLECTION ITEMS TERMINATED BY ':';
- 導入數據
$ cat test6.txt
034,1:2:3:4
035,5:6
036,7:8:9:10
hive> LOAD DATA LOCAL INPATH '/home/work/data/test6.txt' INTO TABLE class_test ;
- 查詢
hive> select student_id_list[3] from class_test;
三、HIVE的join用法
https://blog.csdn.net/shenxiaoming77/article/details/49489713
四棋弥、HIVE的數據刪除
1.刪除指定行
insert overwrite table A select id,name from A where id !=2;
2.刪除表中所有數據
truncate table table_name;
五核偿、HIVE數據分析結果的保存
https://blog.csdn.net/u010159842/article/details/70193687
六、hive中order by,sort by, distribute by, cluster by作用以及用法
orderby 就一個reduce顽染, sortby是指定幾個reduce就是幾個reduce進行排序漾岳,但是并不能保證所有的數據都是有序的
1. order by
Hive中的order by跟傳統的sql語言中的order by作用是一樣的聂薪,會對查詢的結果做一次全局排序,所以說蝗羊,只有hive的sql中制定了order by所有的數據都會到同一個reducer進行處理(不管有多少map藏澳,也不管文件有多少的block只會啟動一個reducer)。但是對于大量數據這將會消耗很長的時間去執(zhí)行耀找。
這里跟傳統的sql還有一點區(qū)別:如果指定了hive.mapred.mode=strict(默認值是nonstrict),這時就必須指定limit來限制輸出條數翔悠,原因是:所有的數據都會在同一個reducer端進行,數據量大的情況下可能不能出結果野芒,那么在這樣的嚴格模式下蓄愁,必須指定輸出的條數。
2. sort by
Hive中指定了sort by狞悲,那么在每個reducer端都會做排序撮抓,也就是說保證了局部有序(每個reducer出來的數據是有序的,但是不能保證所有的數據是有序的摇锋,除非只有一個reducer)丹拯,好處是:執(zhí)行了局部排序之后可以為接下去的全局排序提高不少的效率(其實就是做一次歸并排序就可以做到全局排序了)。
3. distribute by和sort by一起使用
ditribute by是控制map的輸出在reducer是如何劃分的荸恕,舉個例子乖酬,我們有一張表,mid是指這個store所屬的商戶融求,money是這個商戶的盈利咬像,name是這個store的名字
執(zhí)行hive語句:
select mid, money, name from store distribute by mid sort by mid asc, money asc
我們所有的mid相同的數據會被送到同一個reducer去處理,這就是因為指定了distribute by mid生宛,這樣的話就可以統計出每個商戶中各個商店盈利的排序了(這個肯定是全局有序的县昂,因為相同的商戶會放到同一個reducer去處理)。這里需要注意的是distribute by必須要寫在sort by之前陷舅。
4. cluster by
cluster by的功能就是distribute by和sort by相結合倒彰,如下2個語句是等價的:
select mid, money, name from store cluster by mid
select mid, money, name from store distribute by mid sort by mid
如果需要獲得與3中語句一樣的效果:
select mid, money, name from store cluster by mid sort by money
注意被cluster by指定的列只能是降序,不能指定asc和desc蔑赘。