一、概述
- Hive是Apache提供的基于Hadoop的数据仓库管理工具
- Hive提供了类SQL语言来操作Hadoop,底层会将SQL转化为MapReduce来执行,所以效率会比较低
- Hive适应于离线处理
- 要求安装Hive的节点要先安装Hadoop,解压完成之后,在启动Hive的时候自动去找环境变量中的HADOOP_HOME
二、数据库和数据仓库
数据库 数据仓库
数据量 <=GB >=TB
数据种类 单一 - 结构化 多样 - 结构化、半结构化、非结构化
数据来源 相对单一 数据库、日志、爬虫、埋点…
事务 提供了完整的事务(ACID) 弱/无事务
冗余 精简冗余 人为制造冗余 - 副本
场景 为线上系统实时捕获数据 一般存储的是历史数据
系统 OLTP - 联机事务处理 OLAP - 联机分析处理
面向对象 最终面向程序员、DBA 最终面向市场、领导、客户等人员
三、细节
- 在Hive中,每一个database/table在HDFS都会对应一个目录
- Hive中没有主键
- Hive中如果需要指定字段之间的间隔符号,需要在建表的时候就指定,而一个表一旦建立好,那么间隔符号不能改
- 案例:
a. 从person表查数据,将id<=2的数据放入person2中,将gender=male的数据放入person3中
from person insert into person2 select * where id <= 2 insert into person3 select * where gender = ‘male’; - 从person表查数据,将id<=2的数据写入到本地目录中 - 要求本地路径要不存在
insert overwrite local directory ‘/home/hivedata’ select * from person where id <= 2;
c. 从person表中查数据,将查询的数据放入hdfs的person目录下
insert overwrite directory ‘/person’ select * from person; - 向本地目录或者HDFS中的目录写文件的时候只能用overwrite
四、表结构
- 内部表和外部表
a. 自己建表管理原本在HDFS上不存在的数据 - 内部表
b. 需要建表管理在HDFS上已经存在的数据 - 外部表
c. 内部表删除对应的目录一起删除,但是外部表被删除不改变原文件 - 分区表
a. 分区字段在原文件中是不存在,需要在添加数据的时候手动指定
b. 分区的作用是将数据进行分类
create table cities(id int, name string) partitioned by(country string) row format delimited fields terminated by ’ ';
load data local inpath ‘/home/hivedata/cn.txt’ into table cities partition(country=‘china’); - 每一个分区对应一个目录
- 如果在查询的时候加入分区条件,效率会大幅度提高;如果产生了跨分区查询,效率反而会下降
- 自己手动创建的目录并不会被认为称分区,需要手动来添加分区
alter table cities add partition(country=‘japan’) location ‘/user/hive/warehouse/hivedemo.db/cities/country=japan’;
或:msck repair table cities; — 这种方式使用起来比较简单,但是需要注意的是这种方式不稳定可能会添加失败
f. 如果从未分区表中查询数据向已分区表中插入,那么需要开启动态分区机制
开启动态分区机制
set hive.exec.dynamic.partition = true;
关闭严格模式
set hive.exec.dynamic.partition.mode = nostrict;
进行动态分区
insert into table stu partition(class) select sid, sname, sclass from stu_tmp distribute by sclass;
g. 分区的时候可以指定多个字段,在前的字段会自动包含在后的字段
3. 分桶表
a. 分桶表的作用是用于进行数据抽样的
b. 在Hive中,分桶机制默认是不开启的
set hive.enforce.bucketing = true;
create table stu_sam(id int, name string) clustered by(name) into 6 buckets row format delimited fields terminated by ’ ';
insert into table stu_sam select * from stu;
select * from stu_sam tablesample(bucket 2 out of 3 on name);
- 分桶表在进行分桶的时候不能从本地文件加载数据,也不能是外部表,只能从其他表中查询然后插入分桶表中
- 允许一个表既分区又分桶
五、其他
- SerDe:
a. 通过正则表达式来应对实际过程中不规则数据
b. 在正则表达式中设置捕获组来应对不规则数据,在使用的时候,每一个捕获组对应表中的一个字段,意味着捕获组的个数和字段的个数是一致的 — 确定捕获组之间的间隔符号
create table log(ip string, datetime string, timezone string, request string,resource string, protocol string, stateid int)
row format serde ‘org.apache.hadoop.hive.serde2.RegexSerDe’ with serdeproperties(“input.regex” = “(.) – \[(.) (.)\] "(.) (.) (.)” ([0-9]*) -") stored as textfile; - 索引:
a. 索引的作用是能够提高查询速率
b. 数据库中的索引是针对主键自动建立索引,Hive没有主键,所以Hive中默认也不自动建立索引
c. 在Hive中,数据可以建立索引,但是需要指定字段建立索引
建立索引表
create index s_index on table stu(id) as ‘org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler’ with deferred rebuild in table stu_index;
针对表stu产生索引
alter index s_index on stu rebuild;
删除索引
drop index s_index on stu
3. 视图 - view:
a. 视图概念:
- 视图分类:
a. 物化视图:视图是维系在磁盘上
b. 虚拟视图:视图是维系在内存中 - Hive中只支持虚拟视图
create view score_view as select name, math from score; - 视图中要跟随一个查询语句,但是在Hive中,创建视图的时候,这个查询语句并没有被触发 - 即意味着,这个视图创建好之后,只要没有操作这个视图,那么这个视图中此时是没有数据的
- 元数据:
a. 库名、表名、字段名、索引、视图、分区字段、抽样字段等称之为Hive的元数据
b. Hive的元数据是存储在关系型数据库中。关系型数据库目前只支持两种:Derby和MySQL。默认情况下,Hive的元数据是存储在Derby中
c. Hive的元数据只支持西欧编码
d. 如果切换完数据库之后,启动Hive的时候出现READ or UNREAD COMMITED:
i. vim /usr/my.cnf
ii. 文件末尾添加:binlog_format=mixed
iii. 重启mysql: - service mysqld restart
- service mysql restart
- beeline:
a. 远程连接方式:sh beeline -u jdbc:hive2://hadoop01:10000/hivedemo -n root
其中,-u表示连接地址,-n表示用户名
数据类型及函数
一、数据类型
- 将数据类型拆分为基本类型和复杂类型
- 复杂类型:
a. array:数组类型。对应Java中的数组和集合类型
数据:
1,2,4,1,4,4 6,2,3,6,3,6
22,23,6,36,21 64,21,32,54
23,54,74,32 43,63,63,72
语句:
create table nums(num1 array, num2 array) row format delimited fields terminated by ’ ’ collection items terminated by ‘,’;
筛选非空值:
select num1[5] from nums where num1[5] is not null; - map:映射类型。对应Java中的Map类型
数据:
1 amy:15
2 tom:13
3 sam:17
4 alex:16
5 helen:19
语句:
create table infos(id int, info map<string,int>) row format delimited fields terminated by ’ ’ map keys terminated by ‘:’;
非空查询:
select info[‘alex’] from infos where info[‘alex’] is not null;
c. struct:结构体类型。对应的是Java中的对象
语句:
create external table score(info struct<name:string, chinese:int, math:int, english:int>) row format delimited collection items terminated by ’ ’ location ‘/score’;
获取指定属性值:
select info.chinese from score;
扩展:域名解析
com — 一级域名一般适用于标记网站类型
com - commercial - 商业
edu - education - 教育
org - organization - 组织/机构
163 — 二级域名一般是企业/组织名称
baidu.com
163.com
easymall.com
mail — 三级域名一般是企业的应用
mail.163.com
news.baidu.com
二、函数
- concat_ws:用指定符号拼接多个字符串
数据:
mail 163 com
news baidu com
hive apache org
建表:
create table web(app string, name string, type string) row format delimited fields terminated by ’ ‘;
拼接:
select concat_ws(’.’, app, name, type) from web - explode:将数组中元素提取出来形成单独的一行
案例:单词统计
a. 建表管理原始数据
create external table words(word string) row format delimited fields terminated by ‘,’ location ‘/words’;
b. 以空格为单位将单词给拆分成数组
select split(word, ’ ') from words;
c. 将数组中的每一个单词拆分成单独的一行以便于统计
select explode(split(word, ’ ')) from words;
d. 统计个数
select w , count(w) from (select explode(split(word, ’ ')) w from words)ws group by w; - 自定义函数 - UDF - User Define Function。需要继承UDF类,覆盖其中的evaluate方法,将逻辑写在evaluate方法
三、join连接
建表语句:
create external table orders(oid string, dt string, pid string, num int) row format delimited fields terminated by ’ ’ location ‘/order’;
create external table products(pid string, name string, price double) row format delimited fields terminated by ’ ’ location ‘/product’;
查询语句:
select o.oid, o.num * p.price from orders o join products p on o.pid = p.pid;
获取products表中有哪些数据在orders表中出现过
select * from products p left semi join orders o on p.pid = o.pid;
**优化及流程
一、优化
- map side join:如果出现大表和小表的join查询,就可以考虑将小表放入内存中,这样好处在于比从HDFS上读写要快,并且不需要再单独产生Map程序去处理小表
- join优化:如果在join过程中,附带其他查询条件,那么最好先用子查询执行查询条件来减少整体的数据量之后再进行连接查询
3. group by优化:在进行group by的时候实际上是将相同的数据发往一个ReduceTask进行处理。因为数据本身具有倾斜的特性,那么就会导致某个group中的数据多,有些group中的数据少,此时group对应的ReduceTask处理的数据量就不均等, 那么这种情况称之为数据倾斜。set hive.groupby.skewindata=true;会自动的将group by过程拆分成两个阶段,也就类似于MapReduce中的两阶段聚合
4. count distinct优化:count/max/min等聚合函数和distinct同时出现的时候,最好先用子查询进行去重,然后再进行聚合,去重的时候可以设置多个ReduceTask,通过set mapred.reduce.tasks设置数量
5.
- 调整切片数量:本质上调整MapTask的数量。在数据结构相对简单或者处理逻辑相对简单的情况下可以适当增大切片大小来减少MapTask的数量;如果数据结构相对复杂或者处理逻辑相对复杂,可以适当减小切片大小来增多MapTask的数量。可以通过set mapred.max.split.size来调整切片大小
二、流程