hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据映射为一张表,它提供了一系列的工具,可以用来进行数据提取、转化和加载。hive定义了简单的类SQL查询语言,称为HiveSQL。hive在执行过程中会将HQL转换为MapReduce执行,所以它本质上还是一种离线的大数据分析工具,由于hadoop通常会在作业提交和调度时有很大的开销,有较高延迟,因此hive也不能再大规模数据集上实现低延迟的快速查询。hive的最佳适用场景是大数据集的批处理作业,例如网络日志的分析。
数据仓库的特征:
数据库属于OLTP,即联机事物处理系统,一般用来各种具体的业务处理;数据仓库属于OLAP系统,即联机分析处理系统,一般用来分析数据。
数据仓库与数据库的对比:
数据仓库 | 数据库 |
---|---|
为离线分析存储历史数据 | 为线上提供实时数据 |
只支持一写多读,不支持行级改 | 具有完善的crud功能 |
不强调事物 | 具有完整的事物能力 |
制造冗余,提高查询效率 | 尽量避免冗余 |
数据来源多样 | 数据来源单一 |
OLTP | OLAP |
安装:需要jdk环境、hadoop环境、解压即可使用;
运行:运行hive之前需要启动HDFS和MapReduce,启动命令:./bin hive;
注意:hive会将使用中产生的元数据会放在derby数据库,而derby是文件式数据库,而且是在哪里启动的hive,derby文件就在那个目录,更换目录元数据就丢失,而且同时只能连接一个客户端,这很不方便,所以需要借助mysql来保存hive的元数据。
hive常用命令如下:
show databases
:显示数据库;create database test01
:创建数据库;(其实是一个目录)use test01
:切换到test01数据库;create table stu(id int, name string) row format delimited fields terminated by ‘ ’
:创建stu表,包含id、name两个字段,且分隔符为空格;(其实就是一个目录)desc stu
:查看表结构;insert into stu values(1, "张三")
:插入数据(一般不用);select * from stu (where id=1)
:查询,可以跟条件;load data local inpath '/data/1.txt' into table stu
:加载本地文件保存到数据库(HDFS);create table stu2 like stu
:创建一个结构和stu一样的表;insert overwrite table stu2 select * from stu
:将查询结果覆插入到stu2中;from stu insert overwrite table stu2 select * insert overwrite table stu2 select *
:将stu的查询结果覆盖插入到stu2和stu3中insert overwrite local directory ‘/data/1.txt' row format delimited fields terminated by ' ' select * from stu
:将查询结果保存到本地文件(去掉local关键字则是保存到HDFS中);alter table stu2 rename to stu3
:将stu2表重命名为stu3;drop table stu3
:删除stu3表;在上面的基本指令中,默认创建的表就是内部表,由hive先建一张表,然后向这个表里插入数据,这种表不常用;
外部表是在HDFS中已经有了固定格式的数据,然后在hive中创建外部表处理这部分数据,外部表可以管理指定目录下的所有文件,要求是格式统一。删除外部表不会删除真实的文件。创建命令:create external table stu1(id int, name string, score int) row format delimited fields terminated by ' ' location '/hdfs/dir'
。
即对数据进行分区,每个分区一个目录,这样可以避免整表查询从而提高查询效率,外部表和内部表都可以是分区表。分区表在导入数据时需要在hql语句末尾添加**partition(type=‘xx’)**指定分区;实际效果在HDFS中就是一个分区对应一个目录,分区字段就对应目录名,为字段名=字段值(type=xx),相关命令如下。
create table stu(id int, name string) partitioned by (type string) row format delimited fields terminated by ' '
;create external table stu(id int, name string) partitioned by (type string) row format delimited fields terminated by ' ' location '/hdfs/dir'
;alter table stu add partition(type='xx1') location '/hdfs/type=xx1'
;或者msck repair table book
;show partitions stu
;alter table stu drop partition(type='xx1')
;alter table stu partition(type='xx1') rename to partition(type='xx2')
;分桶表概念:
使用分桶表:
create table student(name string, age int) clustered by (name) into 3 buckets row format delimited fields terminated by ' '
;select * from student tablesample(bucket 1 out of 6 on name)
;(1表示从第1个桶开始抽样;6表示抽样步长和比例,即抽取桶数/6个桶的数据,每隔6个桶抽取一次,这个值只能是桶数的因数或倍数);hive0.14之后开始支持事务和行级更新,但缺省不支持,需要额外的属性配置,还需要是分桶表且为orc格式;使用步骤如下:
<property>
<name>hive.support.concurrencyname>
<value>truevalue>
property>
<property>
<name>hive.exec.dynamic.partition.modename>
<value>nonstrictvalue>
property>
<property>
<name>hive.txn.managername>
<value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManagervalue>
property>
<property>
<name>hive.compactor.initiator.onname>
<value>truevalue>
property>
<property>
<name>hive.compactor.worker.threadsname>
<value>1value>
property>
<property>
<name>hive.enforce.bucketingname>
<value>truevalue>
property>
create table t1(id int,name string) clustered by (id) into 3 buckets row format delimited fields terminated by ',' stored as orc
;事务表一般不用
# 数组类型可以通过size(info)获取数组长度
create external table t1(info array) row format delimited fields terminated by ' ' collection items terminated by ',' location '/hdfs/1.txt'
# 列分隔符只能是\t
create external table t1(info map) row format delimited fields terminated by '\t' map keys terminated by ',' location '/hdfs/1.txt'
# 一个map的查询示例
select distinct(info['k']) from t1 where info['k'] is not null;
类似于Javabean
# 没有列分割符了
create external table t1(info struct) row format delimited collection items terminated by ' ' location '/hdfs/1.txt'
# 使用struct示例
select info.age from t1 where info.naem='xx'
UDF即用户自定义函数,使用方法如下:
group by的数据倾斜问题:
join的数据倾斜问题:
/*+mapjoin(t1)*/
连表查询的优化,在hive中,如果连表查询有查询条件,最好改为子查询(原因是count计数操作在hive中只会用一个reduce来实现,所以要先过滤出数据再计数),例如:
# 优化前:
select * from t1 a join t2 b on a.cid=b.id where a.dt='2019-10' and b.price>100;
# 优化后:
select * from (select * from t1 where dt='2019-10') a join (select * from t2 where price>100) b on a.cid=b.id;
参数调优
sqoop:用于HDFS和关系型数据库的数据的相互导入,还可以将数据从关系数据库导出到HBASE,安装sqoop需要jdk和hadoop(导出到Hbase还需要hbase的)的环境变量,并且需要将相关的驱动包(例如mysql驱动包)拷贝到sqoop的lib下,最后在./conf/sqoop-env.sh文件中修改相关的环境变量即可;
基础指令:
./sqoop list-databases --connect jdbc:mysql://hdp01:3306/ -username root -password 1234
;./sqoop list-tables --connect jdbc:mysql://hdp01:3306/db1 -username root -password 1234
;./sqoop import --connect jdbc:mysql://hdp01:3306/db1 --username root --password 1234 --table t1 --target-dir '/data/t1' --fields-terminated-by '|' -m 1
;(还可以通过–query参数指定SQL查询,如:--query 'select * from db1.t1 where $CONDITIONS and id > 10'
)./sqoop export --connect jdbc:mysql://hdp01:3306/db1 --username root --password root --export-dir '/data/t1/' --table t1 -m 1 --fields-terminated-by '|'
;./sqoop import connect jdbc:mysql://hdp01:3306/db1 --username root --password 1234 --table t1 --hbase-table t1 --column-family info --hbase-row-key sid --hbase-create-table
;create table if not exists t1(id int,name String) row format serde 'org.apache.hive.hcatalog.data.JsonSerDe' stored as textfile
;load data local inpath '/data/xxx.json' into table t1
;