Hive 学习笔记
1、Hive安装(只在主节点上安装)
(1)下载安装包到/usr/app/目录下
(2)解压
(3)修改配置文件/etc/profile(添加
export HIVE_HOME=/usr/local/hive-0.9.0-bin
export HADOOP_HOME=/usr/local/hadoop-0.20.2-cdh3u5)
hive-config.sh(添加
export JAVA_HOME=/usr/jdk1.7.0_25
export HIVE_HOME=/usr/local/hive-0.9.0-bin
export HADOOP_HOME=/usr/local/hadoop-0.20.2-cdh3u5)
cd hive-0.9.0-bin/conf/
cp hive-default.xml.template hive-default.xml
cp hive-default.xml.template hive-site.xml
(4)启动Hive
./Hive
2、数据导入
(1)从本地文件系统中导入数据到Hive表;
hive> load data local inpath '/home/hadoop/a.txt' overwrite into table test1;
hive>select * from test1;
(2)从HDFS上导入数据到Hive表;
hive> load data inpath '/user/hadoop/abc/b.txt' overwrite into table test2;
(3)从别的表中查询出相应的数据并导入到Hive表中;
hive> create table test3(id int,name string)
> row format delimited
> fields terminated by '\t'--声明分隔符为制表符;
> stored as textfile;
hive> insert into test3 as select * from test2;
(4)在创建表的时候通过从别的表中查询出相应的记录并插入到所创建的表中
hive> create table test4 as select * from test2;
3、数据导出
(1)导出到本地
hive> insert overwrite local directory '/home/hadoop/data' select * from test;
(2)导出到HDFS
hive> insert overwrite directory '/user/hadoop/abc' select * from he;
(/user/hadoop/abc 为hdfs下目录)
(3)导出到Hive的另一个表中
hive> insert ovewrite into table test5 select * from test3;
4、Hive中的表
(1)内部表
LOCATION '/MYSQL/HIVE/TTD2'--指定表存放的地址
ROW FORMAT DELIMITED
FIELDS TERMINATED BY'\t'
stored as textfile;
alter table test add columns(sex,string); --增加一列(列名sex,数据类型为string)
(2)分区表
--创建分区表
create table partition_table_01
(
sid string,
zid string,
name string,
age int,
sex string)
partitioned by (sex string)
row format delimited
fields terminated by ','
stored as textfile;
--向分区表中插入数据
insert into table partition_table partition (sex='女')
select id,name from test4
WHERE sex='女';
insert into table partition_table partition (sex='男')
select id,name from test4
WHERE sex='n男';
--添加分区
alter table test.test4 add partition(sex='不男不女');
--删除分区
alter 他变了test.test4 drop partition(sex='不男不女');
(3)外部表
--创建外部表
create external table test2(name string,age int)
row format delimited
fields terminated by ','
stored as textfile
location '/user/hadoop/input/';
--特殊说明(外部表的创建和数据的插入同步完成);
--创建外部分区表
(4)桶
--创建桶表
create table bucket_table3(id int,name string,sex string)
clustered by(name) into 3 buckets --按姓名分为3桶
ROW FORMAT DELIMITED
fields terminated by ','
stored as textfile;
-----------------------------------------------------
5、修改表结构
(1)增加列,添加注释
alter table test add columns(sex,string);
(2)删除列
(3)修改表名
alter table test rename test5;
(4)修改字段类型
select cast(sale as double) from test1;
6、join
(1)等连接
(2)多表连接
hive> select a1.name,a2.city,a3.level from test1 a1 join test2 a2 on(a1.id=a2.id) join test3 a3 on(a3.city=a2.city);
zs bj 99999
ls sh 11111
Time taken: 30.679 seconds
(3)多表外连接
a.先连接,再过滤
hive>select a1.name,a2.city from test1 a1 join test2 a2 on(a1.id=a2.id) where a1.id>101 and a2.id<105;
ls sh
Time taken: 15.155 seconds
b.先过滤,后连接
hive> select a1.name,a2.city from test1 a1 join test2 a2 on(a1.id=a2.id and a1.id>101 and a2.id<105);
ls sh
Time taken: 15.114 seconds
(5)map join
select /*+ mapjoin(A)*/ f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802)
7、数据倾斜
倾斜的原因:
使map的输出数据更均匀的分布到reduce中去,是我们的最终目标。由于Hash算法的局限性,按key Hash会或多或少的造成数据倾斜。
大量经验表明数据倾斜的原因是人为的建表疏忽或业务逻辑可以规避的。
解决思路:
Hive的执行是分阶段的,map处理数据量的差异取决于上一个stage的reduce输出,所以如何将数据均匀的分配到各个reduce中,
就是解决数据倾斜的根本所在
具体办法:
内存优化和I/O优化:
驱动表:使用大表做驱动表,以防止内存溢出;Join最右边的表是驱动表;Mapjoin无视join顺序,用大表做驱动表;StreamTable。
1. Mapjoin是一种避免数据倾斜的手段
允许在map阶段进行join操作,MapJoin把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多
在《hive:join遇到问题》有具体操作
在对多个表join连接操作时,将小表放在join的左边,大表放在Jion的右边,
在执行这样的join连接时小表中的数据会被缓存到内存当中,这样可以有效减少发生内存溢出错误的几率
2. 设置参数
hive.map.aggr = true
hive.groupby.skewindata=true 还有其他参数
3.SQL语言调节
比如: group by维度过小时:采用sum() group by的方式来替换count(distinct)完成计算
4.StreamTable
将在reducer中进行join操作时的小table放入内存,而大table通过stream方式读取
5.索引
Hive从0.80开始才有,提供了一个Bitmap位图索引,索引可以加快GROUP BY查询语句的执行速度,用的较少。
8、Hive优化
(1)小文件合并
(2)增加map数,提高Hive的运行效率
(3)尽量原子化操作,避免复杂的SQL
(4)尽量尽早过滤,减少每个阶段的数据量;
(5)创建索引;
(6)JOIN操作时,小表要放在JOIN的左边
(7)使用MAPJOIN,把小表放在内存中,
9、Hive作为历史数据库和关系型数据库的区别?
两者的区别可从以下几个方面比较:
(1)数据存储
(2)表的区别
(3)语法区别
(4)计算模型
10、order by和sort by
(1)order by 会对查询结果集执行一个全局排序,会有一个所有数据都通过一个reducer进行处理的过程。
对于大数据集,该过程会消耗大量时间来执行。
(2)sort by只会在每个reducer中对数据进行排序,也就是执行一个局部排序,可以保证数据是局部有序的,
但不是全局有序的,这样可以提高后面进行的全局排序的效率。
11、sort by和distribute by
alter table test0 change name dt string;
create table test5(id string,name string,ds string)
row format delimited
fields terminated by ','
12、union和union all
合并多个SELECT语句的结果集,需要去重时用union,保留所有值时用union all。
SELECT * FROM table1_name
UNION
SELECT * FROM table2_name;
SELECT * FROM table1_name
UNION ALL
SELECT * FROM table2_name;
--创建一个文本文件
echo 'hadoop' >/home/hadoop/text.txt
--创建一张Hive表
hive -e "create table test(name string)";
--加载数据
load data local inpath '/home/hadoop/test.txt' overwrite into table test;
--查询表
hive -e 'select * from test';
Hive中常用的函数
--取整函数: round
hive> select round(3.1415926) from lxw1234;
3
hive> select round(3.5) from lxw1234;
4
--指定精度取整函数: round
hive> select round(3.1415926,4) from lxw1234;
3.1416
--向下取整函数: floor
hive> select floor(3.1415926) from lxw1234;
3
hive> select floor(25) from lxw1234;
25
--向上取整函数: ceil
hive> select ceil(3.1415926) from lxw1234;
4
hive> select ceil(46) from lxw1234;
46
--向上取整函数: ceiling
hive> select ceiling(3.1415926) from lxw1234;
4
hive> select ceiling(46) from lxw1234;
46
--取随机数函数: rand
hive> select rand() from lxw1234;
0.5577432776034763
hive> select rand() from lxw1234;
0.6638336467363424
hive> select rand(100) from lxw1234;
0.7220096548596434
hive> select rand(100) from lxw1234;
0.7220096548596434
--自然指数函数: exp
hive> select exp(2) from lxw1234;
7.38905609893065
hive> select ln(7.38905609893065) from lxw1234;
2.0
--以10为底对数函数: log10
hive> select log10(100) from lxw1234;
2.0
--以2为底对数函数: log2
hive> select log2(8) from lxw1234;
3.0
hive> select log(4,256) from lxw1234;
4.0
--幂运算函数: pow
hive> select pow(2,4) from lxw1234;
16.0
--幂运算函数: power
hive> select power(2,4) from lxw1234;
16.0
--开平方函数: sqrt
hive> select sqrt(16) from lxw1234;
4.0
--二进制函数: bin
hive> select bin(7) from lxw1234;
111
--十六进制函数: hex
hive> select hex(17) from lxw1234;
11
hive> select hex(‘abc’) from lxw1234;
616263
--反转十六进制函数: unhex
hive> select unhex(‘616263’) from lxw1234;
abc
--进制转换函数: conv
hive> select conv(17,10,16) from lxw1234;
11
hive> select conv(17,10,2) from lxw1234;
10001
--绝对值函数: abs
hive> select abs(-3.9) from lxw1234;
3.9
hive> select abs(10.9) from lxw1234;
10.9
--正取余函数: pmod
hive> select pmod(9,4) from lxw1234;
1
hive> select pmod(-9,4) from lxw1234;
3
--正弦函数: sin
hive> select sin(0.8) from lxw1234;
0.7173560908995228
--反正弦函数: asin
hive> select asin(0.7173560908995228) from lxw1234;
0.8
hive> select cos(0.9) from lxw1234;
0.6216099682706644
--反余弦函数: acos
hive> select acos(0.6216099682706644) from lxw1234;
0.9
--positive 函数: positive
hive> select positive(-10) from lxw1234;
-10
hive> select positive(12) from lxw1234;
12
--negative 函数: negative
hive> select negative(-5) from lxw1234;
5
hive> select negative(8) from lxw1234;
-8
--字符串拼接:concat
hive> select concat('abc','def') from test;
abcdef
--带分隔符字符串连接函数:concat_ws
hive> select concat_ws(',','abc','def','gh') from test;
abc,def,gh
--数组转换成字符串的函数:concat_ws
hive> select concat_ws('|',array('a','b','c')) from test;
a|b|c
--小数位 格式化成字符串函数:format_number
hive> select format_number(5.23456,3) from test;
5.235
--字符串截取函数:substr,substring
hive> select substr('abcde',3) from test;
cde
hive> select substring('abcde',3) from test;
cde
hive> select substr('abcde',-1) from test; (和 ORACLE 相同)
e
--字符串截取函数:substr,substring
hive> select substr('abcde',3,2) from test;
cd
hive> select substring('abcde',3,2) from test;
cd
hive>select substring('abcde',-2,2) from test;
de
--字符串 查找函数: instr
hive> select instr('abcdf','df') from test;
4--(abcdef中df首次出现的位置)
--字符串 长度 函数: length
hive> select length('abc') from test;
3
--字符串 查找函数:locate
hive> select locate('a','abcda',1) from test;
1
hive> select locate('a','abcda',2) from test;
5
--字符串 转换成 map 函数 : str_to_map
hive> select str_to_map('k1:v1,k2:v2') from test;
{"k2":"v2","k1":"v1"}
hive> select str_to_map('k1=v1,k2=v2',',','=') from test;
{"k2":"v2","k1":"v1"}
--字符串转大写函数:upper,ucase
hive> select upper('abSEd') from test;
ABSED
--字符串转小写函数:lower,lcase
hive> select lower('abSEd') from test;
absed
--去空格函数:trim
hive> select trim(' abc ') from test;
abc
--左边去空格函数:ltrim
hive> select ltrim(' abc ') from test;
abc
--右边 去空格函数:rtrim
hive> select rtrim(' abc ') from test;
abc
--重复字符串函数:repeat
hive> select repeat('abc',5) from test;
abcabcabcabcabc
--左补足函数:lpad
hive> select lpad('abc',10,'td') from test;
tdtdtdtabc
-- 右补足函数:rpad
hive> select rpad('abc',10,'td') from test;
abctdtdtdt
--分割字符串函数: split
hive> select split('abtcdtef','t') from test;
["ab","cd","ef"]
--集合查找函数: find_in_set
hive> select find_in_set('ab','ef,ab,de') from test;
2
hive> select find_in_set('at','ef,ab,de') from test;
0
日期函数
类型转换
cast(date as date)
返回值:date
cast(date as string)
返回值:date所代表的年月日将以string形式返回;
cast(string as date)
返回值:如果string的格式为yyyy-MM-dd,则返回date类型的数据,反之为null.
cast(date as timestamp)
返回值:基于当地的时区,生成时间戳
cast(timestamp as date)
返回值:date
--UNIX时间戳转日期函数: from_unixtime
hive> select from_unixtime(1323308943,'yyyyMMdd') from lxw1234;
20111208
--获取当前 UNIX 时间戳函数: unix_timestamp
hive> select unix_timestamp() from lxw1234;
1323309615
--日期转 UNIX 时间戳函数: unix_timestamp
hive> select unix_timestamp('2011-12-07 13:01:03') from lxw1234;
1323234063
--指定格式日期转 UNIX 时间戳函数: unix_timestamp
hive> select unix_timestamp('20111207 13:01:03','yyyyMMdd HH:mm:ss') from lxw1234;
1323234063
--日期时间转日期函数: to_date
Hive 函数大全 http://lxw1234.com
27
hive> select to_date('2011-12-08 10:03:01') from lxw1234;
2011-12-08
--日期转年函数: year
hive> select year('2011-12-08 10:03:01') from lxw1234;
2011
hive> select year('2012-12-08') from lxw1234;
2012
--日期转月函数: month
hive> select month('2011-12-08 10:03:01') from lxw1234;
12
hive> select month('2011-08-08') from lxw1234;
8
--日期转天函数: day
hive> select day('2011-12-08 10:03:01') from lxw1234;
8
hive> select day('2011-12-24') from lxw1234;
24
-日期转小时函数: hour
hive> select hour('2011-12-08 10:03:01') from lxw1234;
--日期转分钟函数: minute
hive> select minute('2011-12-08 10:03:01') from lxw1234;
3
--日期转秒函数: second
hive> select second('2011-12-08 10:03:01') from lxw1234;
1
--日期转周函数: weekofyear
hive> select weekofyear('2011-12-08 10:03:01') from lxw1234;
49
--日期比较函数: datediff
hive> select datediff('2012-12-08','2012-05-09') from lxw1234;
213
--日期增加函数: date_add
hive> select date_add('2012-12-08',10) from lxw1234;
2012-12-18
--日期减少函数: date_sub
hive> select date_sub('2012-12-08',10) from lxw1234;
2012-11-28
条件 函数
--If 函数: if
hive> select if(1=2,100,200) from lxw1234;
200
hive> select if(1=1,100,200) from lxw1234;
100
--非空 查找函数: COALESCE
hive> select COALESCE(null,'100','50′) from lxw1234;
100
--条件判断函数:CASE
hive> Select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end from lxw1234;
mary
hive> Select case 200 when 50 then 'tom' when 100 then 'mary' else 'tim' end from lxw1234;
tim
--条件判断函数:CASE
hive> select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end from lxw1234;
mary
--分词 函数 :sentences
hive> select sentences('hello word!hello hive,hi hive,hello hive') from test;
[["hello","word"],["hello","hive","hi","hive","hello","hive"]]
--分词后统计一起出现频次最高的的 TOP-K
hive> SELECT ngrams(sentences('hello word!hello hive,hi hive,hello hive'),2,2) FROM test;
[{"ngram":["hello","hive"],"estfrequency":2.0},{"ngram":["hive","hello"],"estfrequency":1.0}]
--分词后统计与指定单词一起出现频次最高的的 TOP-K
hive> SELECT context_ngrams(sentences('hello word!hello hive,hi hive,hello hive'),array('hello',null),3) FROM test;
[{"ngram":["hive"],"estfrequency":2.0},{"ngram":["word"],"estfrequency":1.0}]
hive> SELECT context_ngrams(sentences('hello word!hello hive,hi hive,hello hive'),array(null,'hive'),3) FROM test;
[{"ngram":["hello"],"estfrequency":2.0},{"ngram":["hi"],"estfrequency":1.0}]
该查询中,统计的是与’hive’一起出现,并且在 hive 之前的频次最高的 TOP-3